I have the following code:
for(var i = 0; i < list.length; i++){
mc_cli.get(list[i], function(err, response) {
do_something(i);
});
}
mc_cli
is a connection to a memcached database. As you can imagine, the callback function is asynchronous, thus it may be executed when the for loop already ended. Also, when calling in this way do_something(i)
it always uses the last value of the for loop.
I tried with a closure in this way
do_something((function(x){return x})(i))
but apparently this is again using always the last value of the index of the for loop.
I also tried declaring a function before the for loop like so:
var create_closure = function(i) {
return function() {
return i;
}
}
and then calling
do_something(create_closure(i)())
but again without success, with the return value always being the last value of the for loop.
Can anybody tell me what am I doing wrong with closures? I thought I understood them but I can't figure why this is not working.
Using ES6 (typescript) you can use the benefits of
async
andawait
:This is the asynchronous-function-inside-a-loop paradigm, and I usually deal with it using an immediately-invoked-anonymous-function. This ensures that the asynchronous functions get called with the correct value of the index variable.
Okay, great. So all the asynchronous functions have been started up, and the loop exits. Now, there is no telling when these functions will complete, due to their asynchronous nature, or in what order they will complete. If you have code that needs to wait until all these functions have completed before executing, I recommend keeping a simple count of how many functions have finished:
Try this, using the
async/await
syntax andPromise
This will stop the loop in each cycle until the
next()
function is triggeredI know this is a old thread but anyway adding my answer. ES2015
let
has the feature of rebinding the loop variable on each iteration, so it maintains the value of loop variable in asynchronous callbacks, so you can try the below one:But anyway, it's better to use
forEach
or create a closure using immediately-invoked-function, sincelet
is ES2015 feature and might not be support all browsers and implementations. From here underBindings ->let->for/for-in loop iteration scope
I can see it isn't supported till Edge 13 and even till Firefox 49 (I haven't checked in these browsers). It even says it's not supported with Node 4, but I personally tested and it seems it is supported.ES2017: You can wrap the async code inside a function(say XHRPost) returning a promise( Async code inside the promise).
Then call the function(XHRPost) inside the for loop but with the magical Await keyword. :)
If you want to run asynchronous functions inside a loop, but still want to keep the index or other variables after a callback gets executed you can wrap your code in an IIFE (immediately-invoked function expression).