简体   繁体   English

未捕获的TypeError: <function> 不是功能

[英]Uncaught TypeError: <function> is not a function

I am pretty new to Javascript and I've across an issue I can't seem to understand. 我对Java语言还很陌生,遇到了一个我似乎无法理解的问题。 The console is complaining saying it is not recognising the function. 控制台抱怨说无法识别该功能。

I have the following code (GraphActions.js): 我有以下代码(GraphActions.js):

var VentureDispatcher = require('../dispatcher/VentureDispatcher');
var GraphStoreConstants = require('../constants/GraphStoreConstants');
var StockService = require('../utils/StockService');

var GraphActions = {};

  GraphActions.getGraphData = function(request){
    //have the API call here.
    VentureDispatcher.handleViewAction({
      actionType: GraphStoreConstants.GET_GRAPH_DATA,
      data: request
    });
    StockService.getHistoricStockData(request);
  };

  GraphActions.recieveGraphData = function(response){
    VentureDispatcher.handleServerAction({
      actionType: GraphStoreConstants.GRAPH_DATA_RESPONSE,
      response: response
    });
  };

  GraphActions.test = function(){
    console.debug("found this.");
  };

module.exports = GraphActions;

And the following Javascript file which is calling the function within the code above: 以下是在上述代码中调用该函数的Javascript文件:

var request = require('superagent');
var GraphActions = require('../actions/GraphActions');

var StockService = {

  getHistoricStockData: function(symbol){
      request.post('http://localhost:8080/historicalData')
             .send({
                        "symbol":"GOOG",
                        "from":"2016-06-01",
                        "to":"2016-07-01"
                    })
             .set('Content-Type','application/json')
             .end(function(err,res){
               if(err || !res.ok){
                  console.error('Error making request!');
               }else {
                  console.debug(JSON.stringify(res.body));
                  GraphActions.recieveGraphData(res.body);
              }
            });
  }
};

module.exports = StockService;

The console is throwing the following error and not too sure why: venture-stock.js:44673 Uncaught TypeError: GraphActions.recieveGraphData is not a function. 控制台将引发以下错误,但并不太确定原因:Venture-stock.js:44673未捕获的TypeError:GraphActions.recieveGraphData不是一个函数。

Does anyone understand why this is happening? 有谁知道为什么会这样? The same method has been called in another place with no problem. 相同的方法已在另一个位置成功调用。

When debugging the code and evaluating GraphAction object in the above code I get the following where the functions defined above are not available: 当调试代码并评估以上代码中的GraphAction对象时,我得到以下内容,其中上面定义的功能不可用:

在此处输入图片说明

Where as in another location, the functions are available: 在其他位置,这些功能可用:

在此处输入图片说明

Any help would be appreciated! 任何帮助,将不胜感激!

It happens because of a circular reference among your modules. 发生这种情况是因为模块之间存在循环引用。 The module GraphActions requires the module StockService , which also requires GraphActions . GraphActions模块需要StockService模块,后者需要GraphActions It doesn't matter if what's actually needed in StockService it's the recieveGraphData method, while the method that requires StockService is getGraphData : the module loader doesn't have this level of code analysis. 不管实际需要在StockService什么是recieveGraphData方法,而需要StockService的方法是getGraphData :模块加载器没有这种级别的代码分析。 require would always return the whole module, so it's a circular reference. require将始终返回整个模块,因此它是一个循环引用。

So, what happens in these cases? 那么,在这些情况下会发生什么?

The module loader, when loading GraphActions , meets require('../utils/StockService') , then stops the execution of GraphActions in order to load StockService . 模块加载器在加载GraphActions时满足require('../utils/StockService') ,然后停止执行GraphActions以便加载StockService At this point, the exported properties of GraphActions are... none. 此时, GraphActions的导出属性为...无。 So that's why in StockService you get an empty object. 这就是为什么在StockService会得到一个空对象的原因。

Solution A 解决方案A

Merge the two modules in one, eg 将两个模块合并为一个,例如

var GraphService = {
    getGraphData: function(request) {
        ...
        GraphService.getHistoricStockData(request);
    },
    recieveGraphData: function(response) { ... },
    getHistoricStockData: function(symbol) {
        ...
        GraphService.recieveGraphData(res.body);
    }
};
module.exports = GraphService;

Solution B 解决方案B

It's the opposite, ie decouple getGraphData and recieveGraphData in two different modules. 相反,即在两个不同的模块中解耦getGraphDatarecieveGraphData I don't really like this one, because it can lead to excessive module fragmentation. 我真的不喜欢这个,因为它可能导致过多的模块碎片。

Solution C (recommended) 解决方案C(推荐)

As long as CommonJS is used, you can take advantage of using require wherever you want, so in StockService.js you'd do: 只要使用CommonJS,您就可以在任何require地方利用require ,因此在StockService.js您可以这样做:

getHistoricStockData: function(symbol) {
    request.post('http://localhost:8080/historicalData')
        ...
        .end(function(err, res) {
            ...
            var GraphActions = require('../actions/GraphActions');
            GraphActions.recieveGraphData(res.body);
        });
}

Now, since the execution will not immediately require GraphActions , the module will be loaded later when all its dependencies are fully loaded, so you'll get a fully working module. 现在,由于执行将不会立即需要GraphActions ,因此将在模块的所有依赖项完全加载后再加载该模块,因此您将获得一个完全正常工作的模块。

Differences with ES2015 modules ES2015模块的差异

In ES6, you cannot use import outside the root level, ie you can't use import inside a function. 在ES6中,不能在根级别之外使用import ,即,不能在函数内部使用import So you couldn't use solution C with ES6 syntax? 因此,您不能将解决方案C与ES6语法一起使用?

Actually that wouldn't be necessary to begin with, because CommonJS module resolution is different than ES6's, the latter being more advanced. 实际上,一开始就没有必要,因为CommonJS模块的解析度不同于ES6的解析度,后者更为先进。 So, you'd have written: 因此,您将编写:

import * as StockService from '../utils/StockService';
...
export function getGraphData(request) {
    ...
    StockService.getHistoricStockData(request);
};
export function recieveGraphData(response) { ... };
export function test() { ... };

and in StockService.js : 并在StockService.js

import * as GraphActions from '../actions/GraphActions';
...
export function getHistoricStockData(symbol) {
    request.post('http://localhost:8080/historicalData')
        .send( ... )
        .set('Content-Type','application/json')
        .end(function(err, res) {
             ...
             GraphActions.recieveGraphData(res.body);
        });
};

So what happens here? 那么这里发生了什么? GraphActions.js is loaded, the import statement is reached, the execution of the module stops and then StockService is loaded. 加载GraphActions.js ,到达import语句, 停止执行模块 ,然后加载StockService So far, it's the same as CommonJS. 到目前为止,它与CommonJS相同。

In StockService , the loader would meet the import statement, then the execution of GraphActions resumes and the whole module is correctly exported. StockService ,加载程序将满足import语句,然后恢复执行GraphActions并正确导出整个模块。 So you'd be golden from the start with ES6. 因此,从一开始,ES6就让您大开眼界。

This will lead us to 这将导致我们

Solution D (most recommended... if you can) 解决方案D(如果可以的话,建议使用...)

Since you're already using Babel, use the plugin "transform-es2015-modules-commonjs" or "preset-es2015" and use ES6 modules instead. 由于您已经在使用Babel,请使用插件“ transform-es2015-modules-commonjs”或“ preset-es2015”并使用ES6模块。

Hope this cleared your doubts! 希望这消除了您的疑虑!

(Btw, it's "receive", not "recieve" ;) (顺便说一句,它是“接收”,而不是“接收”;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM