未捕获的TypeError:<function>不是函数

时间:2016-07-24 22:40:31

标签: javascript webpack

我对Javascript很陌生,而且我遇到了一个我似乎无法理解的问题。控制台抱怨说它没有认识到这个功能。

我有以下代码(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对象时,我得到以下定义的函数不可用的内容:

enter image description here

在其他位置,功能可用:

enter image description here

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

这是因为您的模块之间存在循环引用。模块GraphActions需要模块StockService,其中需要GraphActionsStockService recieveGraphData方法StockService实际需要什么并不重要,而需要getGraphData的方法是require :模块加载器没有这种级别的代码分析。 GraphActions将始终返回整个模块,因此它是循环引用。

那么,在这些情况下会发生什么?

模块加载器在加载require('../utils/StockService')时遇到GraphActions,然后停止执行StockService以加载GraphActions。此时,StockService的导出属性为...... none。这就是var GraphService = { getGraphData: function(request) { ... GraphService.getHistoricStockData(request); }, recieveGraphData: function(response) { ... }, getHistoricStockData: function(symbol) { ... GraphService.recieveGraphData(res.body); } }; module.exports = GraphService; 中你得到一个空对象的原因。

解决方案A

将两个模块合并为一个,例如

getGraphData

解决方案B

相反,即在两个不同的模块中解耦recieveGraphDatarequire。我不太喜欢这个,因为它会导致过多的模块碎片。

解决方案C(推荐)

只要使用CommonJS,您就可以在任意位置使用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

现在,由于执行将立即需要import,因此稍后当所有依赖项完全加载时,模块将被加载,因此您将获得一个完全正常工作的模块

与ES2015模块的区别

在ES6中,您不能在根级别之外使用import,即您无法在函数内使用import * as StockService from '../utils/StockService'; ... export function getGraphData(request) { ... StockService.getHistoricStockData(request); }; export function recieveGraphData(response) { ... }; export function test() { ... }; 。所以你不能使用带有ES6语法的解决方案C?

实际上开始时并不是必需的,因为CommonJS模块的分辨率与ES6不同,后者更为先进。所以,你已经写过了:

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语句,模块的执行停止,然后加载StockService。到目前为止,它与CommonJS相同。

import中,加载程序将满足GraphActions语句,然后执行Function Test{ while($true){ write-host "I want this to refresh every time" Start-Sleep -Seconds 4 cls } } Write-Host "I want this to be at the screen always" Test 简历并正确导出整个模块。所以你从ES6开始就是金色的。

这将引导我们

解决方案D(最推荐......如果可以的话)

由于您已经在使用Babel,请使用插件&#34; transform-es2015-modules-commonjs&#34;或&#34;预设-es2015&#34;而是使用ES6模块。

希望这清除了你的疑虑!

(顺便说一句,它&#34;收到#34;而不是&#34;收到&#34 ;;)