I have just started programming with JS and Node, and I haven't got used to asynchronous stuff yet. Basically, i have the following code:
for (var i=0, len=sources.length; i<len; i++) {
processSource(sources[i], function(info) {
doesOtherStuff(sources[i], info);
});
}
It doesn't really work, because, as processSource takes a while to finish, the function doesOtherStuff is called with unmatching arguments, like sources[2] and the processed info for sources[0].
What is the correct way of dealing with this? Is there something inherently wrong with the design of these functions. (both processSource and doesOtherStuff are my functions).
-
1"int" hmmmm, that seems wrong.epascarello– epascarello2013年12月12日 17:47:58 +00:00Commented Dec 12, 2013 at 17:47
-
Typo, sorry =P. Problem still holds.Márcio Paiva– Márcio Paiva2013年12月12日 17:50:11 +00:00Commented Dec 12, 2013 at 17:50
-
you show me a reason to use javascript forEach!damphat– damphat2013年12月12日 19:11:08 +00:00Commented Dec 12, 2013 at 19:11
4 Answers 4
The problem with the code is the fact that i is not want you expect it to be.
When the loop completes, the function-level variable i has the value of sources.length. So when doesOtherStuff runs that is what the inner function uses.
for (var i=0, len=sources.length; i<len; i++) {
(function(i) {
processSource(sources[i], function(info) {
doesOtherStuff(sources[i], info);
});
})(i);
}
3 Comments
javascript style could help you:
sources.forEach(function (e) {
processSource(e, function(info) {
doesOtherStuff(e, info);
});
}
Comments
Try using Caolan's async library - this works on Node and in the browser. You can then do something like this:
async.map(sources, function (item, callback) {
// Do your actions on each item here
processSource(item, function (info) {
var result = doOtherStuff(item, info);
// Send callback so the next item can be processed
callback(null, result);
});
}, function (err, results) {
// Handle the processed results here
});
1 Comment
1) Use var instead of int.
2) You have a superfluous ) in your call to processSource.
processSource(sources[i], function(info) /* No 2nd ')' here */ {
doesOtherStuff(sources[i], info);
});
should work.