I am pretty new to Javascript and I've across an issue I can't seem to understand. The console is plaining saying it is not recognising the function.
I have the following code (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:
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.
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:
Where as in another location, the functions are available:
Any help would be appreciated!
I am pretty new to Javascript and I've across an issue I can't seem to understand. The console is plaining saying it is not recognising the function.
I have the following code (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:
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.
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:
Where as in another location, the functions are available:
Any help would be appreciated!
Share Improve this question asked Jul 24, 2016 at 22:40 MathanMVMathanMV 4121 gold badge6 silver badges16 bronze badges 4- I guess you're piling your modules in a big js file. What do you use? Are you sure it's the same module? Do you have any circular references among the modules? – MaxArt Commented Jul 24, 2016 at 22:44
- I'm using Webpack with a babel loader to pile the modules into one big js file. And yes, both occasions I was importing the same module (i.e var GraphActions = require('../actions/GraphActions');). I believe I don't have any circular references. A function (A) in GraphAction.js calls a function in StockService.js (B) which then calls a different function in GraphAction.js (C). I don't think this would count as a circular ref if they are calling different functions? – MathanMV Commented Jul 24, 2016 at 22:55
- The point is that if any of the required modules in GraphAction has GraphAction in its dependency tree, the exported object will be temporary empty there. So yes, if everything is synchronous you'll have a problem. I'll set up an answer later. – MaxArt Commented Jul 25, 2016 at 5:52
- Cheers, that makes sense. I've separated the actions that handle server responses into a separate file to e around this problem. Will accept your answer once plete. – MathanMV Commented Jul 25, 2016 at 14:05
1 Answer
Reset to default 7It happens because of a circular reference among your modules. The module GraphActions
requires the module StockService
, which also requires 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. require
would always return the whole module, so it's a circular reference.
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
. At this point, the exported properties of GraphActions
are... none. So that's why in StockService
you get an empty object.
Solution A
Merge the two modules in one, e.g.
var GraphService = {
getGraphData: function(request) {
...
GraphService.getHistoricStockData(request);
},
recieveGraphData: function(response) { ... },
getHistoricStockData: function(symbol) {
...
GraphService.recieveGraphData(res.body);
}
};
module.exports = GraphService;
Solution B
It's the opposite, i.e. decouple getGraphData
and recieveGraphData
in two different modules. I don't really like this one, because it can lead to excessive module fragmentation.
Solution C (remended)
As long as CommonJS is used, you can take advantage of using require
wherever you want, so in StockService.js
you'd do:
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.
Differences with ES2015 modules
In ES6, you cannot use import
outside the root level, i.e. you can't use import
inside a function. So you couldn't use solution C with ES6 syntax?
Actually that wouldn't be necessary to begin with, because CommonJS module resolution is different than ES6's, the latter being more advanced. 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
:
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. So far, it's the same as CommonJS.
In StockService
, the loader would meet the import
statement, then the execution of GraphActions
resumes and the whole module is correctly exported. So you'd be golden from the start with ES6.
This will lead us to
Solution D (most remended... if you can)
Since you're already using Babel, use the plugin "transform-es2015-modules-monjs" or "preset-es2015" and use ES6 modules instead.
Hope this cleared your doubts!
(Btw, it's "receive", not "recieve" ;)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742367024a4430517.html
评论列表(0条)