1

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).

asked Dec 12, 2013 at 17:46
3
  • 1
    "int" hmmmm, that seems wrong. Commented Dec 12, 2013 at 17:47
  • Typo, sorry =P. Problem still holds. Commented Dec 12, 2013 at 17:50
  • you show me a reason to use javascript forEach! Commented Dec 12, 2013 at 19:11

4 Answers 4

2

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);
}
answered Dec 12, 2013 at 17:51
Sign up to request clarification or add additional context in comments.

3 Comments

So this is actually standard, is is it more like a hack to code that was bad-written in the first place? I'm still trying to get my head around event-driven.
That pattern is commonly called an IIFE (immediately-invoked function expression) in case you're looking for more information about it.
Love this, also we can do +function() {...}(i); :)
1

javascript style could help you:

sources.forEach(function (e) {
 processSource(e, function(info) {
 doesOtherStuff(e, info);
 });
}
answered Dec 12, 2013 at 19:03

Comments

0

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
});
answered Dec 12, 2013 at 17:53

1 Comment

Wouldn't this be an overkill? Or is this library used in the majority of node projects, (like Boost library to C++) ?
0

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.

answered Dec 12, 2013 at 17:50

3 Comments

Sorry, those were typos, not actually the issue. Problem is indeed what epascarello has guessed.
To avoid typos you should never type code into SO but copy it from your source.
Sorry... The code was actually a little more complex, so i tried to reduce it to be clearer about the issue. Guess it didn't help

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.