我对Java语言还很陌生,遇到了一个我似乎无法理解的问题。控制台抱怨说无法识别该功能。
我有以下代码(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;
以下是在上述代码中调用该函数的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;
控制台抛出以下错误,但不太确定原因:
venture-stock.js:44673未捕获的TypeError:GraphActions.recieveGraphData不是函数。
有谁知道为什么会这样?相同的方法已在另一个位置成功调用。
在上面的代码中调试代码并评估GraphAction对象时,我得到以下内容,其中上面定义的功能不可用:
在其他位置,这些功能可用:
任何帮助,将不胜感激!
最佳答案
发生这种情况是由于模块之间存在循环引用。模块GraphActions
需要模块StockService
,该模块也需要GraphActions
。 StockService
中实际需要的是recieveGraphData
方法都没有关系,而需要StockService
的方法是getGraphData
:模块加载器没有这种级别的代码分析。 require
将始终返回整个模块,因此它是一个循环引用。
那么,在这些情况下会发生什么?
模块加载器在加载GraphActions
时遇到require('../utils/StockService')
,然后停止执行GraphActions
以便加载StockService
。此时,GraphActions
的导出属性为...无。这就是为什么在StockService
中得到一个空对象的原因。
解决方案A
将两个模块合并为一个,例如
var GraphService = {
getGraphData: function(request) {
...
GraphService.getHistoricStockData(request);
},
recieveGraphData: function(response) { ... },
getHistoricStockData: function(symbol) {
...
GraphService.recieveGraphData(res.body);
}
};
module.exports = GraphService;
解决方案B
相反,即在两个不同的模块中解耦
getGraphData
和recieveGraphData
。我真的不喜欢这个,因为它可能导致过多的模块碎片。解决方案C(推荐)
只要使用CommonJS,就可以在任何需要的地方利用
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);
});
}
现在,由于执行不会立即需要
GraphActions
,因此将在模块的所有依赖项完全加载后再加载该模块,因此您将获得一个完全正常工作的模块。ES2015模块的差异
在ES6中,您不能在根级别之外使用
import
,即您不能在函数内部使用import
。因此,您不能将解决方案C与ES6语法一起使用?实际上,一开始就没有必要,因为CommonJS模块的分辨率不同于ES6的分辨率,后者更为先进。因此,您将编写:
import * as StockService from '../utils/StockService';
...
export function getGraphData(request) {
...
StockService.getHistoricStockData(request);
};
export function recieveGraphData(response) { ... };
export function test() { ... };
并在
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);
});
};
那么这里发生了什么?加载
GraphActions.js
,到达import
语句,模块的执行停止,然后加载StockService
。到目前为止,它与CommonJS相同。在
StockService
中,加载程序将满足import
语句,然后恢复执行GraphActions
,并且正确导出了整个模块。因此,从一开始使用ES6便会变得无与伦比。这将导致我们
解决方案D(如果可以的话,建议使用...)
由于您已经在使用Babel,请使用插件“ transform-es2015-modules-commonjs”或“ preset-es2015”并使用ES6模块。
希望这能消除您的疑虑!
(顺便说一句,它是“接收”,而不是“接收”;)
关于javascript - 未捕获的TypeError:<function>不是函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38557550/