-
-
Save momadacoding/c43c5f463182c34e49cb0ffe27595737 to your computer and use it in GitHub Desktop.
javascript loop with async callback handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
// ================================================= | |
// a common question that pops up is | |
// 'why do my async functions use the final value of my loop variable instead of the one they are called with'? | |
// its because they refer directly to the loop variable and its last value | |
// the solutions are various ways to bind the loop variable in a new scope | |
// | |
// this gist shows different ways to handle a loop that spawns an async function that depends on the loop index | |
// ================================================= | |
// if you run this whole file it will print 40 40 40 40 40 | |
// if you run this by itself it will print 5 5 5 5 5 | |
for(var i=0;i<5;++i) { | |
setTimeout(function() { | |
console.log(i); | |
}, | |
500); | |
} | |
// first a couple of supporting functions | |
// this is good because 'this' could be any object | |
function f() { | |
console.log(this); | |
} | |
// return a function that captures the parameter i | |
function a(i) { | |
return function() { | |
console.log(i); | |
} | |
} | |
// now the loops | |
// bind the variable as the context 'this' | |
for(var i=5;i<10;++i) { | |
setTimeout(f.bind(i) // is this a questionable practice? I'm not sure | |
,1500); | |
} | |
// same as f() but anonymous | |
for(var i=10;i<15;++i) { | |
setTimeout( | |
function() { | |
console.log(this); | |
}.bind(i) | |
,2000); | |
} | |
// call a separate function that returns a function | |
// which binds the parameter | |
for(var i=15;i<20;++i) { | |
setTimeout( | |
a(i) | |
,3500); | |
} | |
// same as function a(i) but anonymous IIFE | |
// note that in this context the surrounding parens usually required for an IIFE | |
// are not needed because the function parameter is an expression | |
for(var i=20;i<25;++i) { | |
setTimeout( | |
function(j) { | |
return function() { | |
console.log(j); | |
} | |
}(i) | |
,4000); | |
} | |
// same as before but anonymous IIFE with the usual parens | |
for(var i=25;i<30;++i) { | |
setTimeout( | |
(function(j) { | |
return function() { | |
console.log(j); | |
} | |
})(i) | |
,4500); | |
} | |
// ======================================================= | |
// comment the rest out if you don't have es6 (node 4) | |
// ======================================================= | |
// 'let' effectively creates a new instance of i in each iteration | |
for(let i=30;i<35;++i) { | |
setTimeout( | |
function() { | |
console.log(i); | |
} | |
,5000); | |
} | |
// simiarl to IIFE above but with arrow functions | |
// in this case the parens surrounding the IIFE seem to be required at least in node 4.1 | |
for(var i=35;i<40;++i) { | |
setTimeout( | |
(j => { | |
return () => { | |
console.log(j); | |
}; | |
})(i) | |
,5500); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment