Asynchronous Process inside a javascript for loop -
i running event loop of following form:
var i; var j = 10; (i = 0; < j; i++) { asycronouseprocess(callbackfunction() { alert(i); }); } what display series of alerts showing numbers 0 through 10. problem time call function triggered loop has gone through few iterations , displays higher value of i. recommendation on how fix this?
the for loop runs completion while asynchronous operations started. when complete time in future , call callbacks, value of loop index variable i @ last value callbacks.
this because for loop not wait asynchronous operation complete before continuing on next iteration of loop , because async callbacks called time in future. thus, loop completes iterations , callbacks called when async operations finish. such, loop index "done" , sitting @ final value callbacks.
to work around this, have uniquely save loop index separately each callback. in javascript, way capture in function closure. can either done creating inline function closure purpose (first example shown below) or can create external function pass index , let maintain index uniquely (second example shown below).
as of 2016, if have up-to-spec es6 implementation of javascript, can use let define for loop variable , uniquely defined each iteration of for loop (third implementation below). but, note late implementation feature in es6 implementations have make sure execution environment supports option.
use .foreach() iterate since creates own function closure
somearray.foreach(function(item, i) { asycronouseprocess(function(item) { console.log(i); }); }); create own function closure using iife
var j = 10; (var = 0; < j; i++) { (function(cntr) { // here value of passed argument cntr // , captured in function closure each // iteration of loop can have it's own value asycronouseprocess(function() { console.log(cntr); }); })(i); } create or modify external function , pass variable
if can modify asycronouseprocess() function, pass value in there , have asycronouseprocess() function cntr callback this:
var j = 10; (var = 0; < j; i++) { asycronouseprocess(i, function(cntr) { console.log(cntr); }); } use es6 let
if have javascript execution environment supports es6, can use let in for loop this:
const j = 10; (let = 0; < j; i++) { asycronouseprocess(function() { console.log(i); }); } note: es6 feature 1 of later es6 features js engines support have make sure specific feature supported in environment.
Comments
Post a Comment