Skip to content Skip to sidebar Skip to footer

Javascript Code Running In Wrong Sequence

I have code like this: var newArr = []; var arr = [{a: 1}, {a:2}, {a:3}, {a:4}]; arr.forEach(function(item) { setTimeout(function(){item.a = item.a + 1;}, 3000); newArr.pus

Solution 1:

It's not clear whether you were using the timeout to substitute some asynch behavior or whether the timeout is integral to what you're trying to solve. We'll get to them both. I'd written about turning setTimeout() into a promises pattern, in my blog. So, first, turn use of setTimeout() into a promise-based pattern:

functiontimeout(delay) {
    returnnewPromise( 
       (resolve, reject) =>setTimeout( resolve, delay )
    )
} // timeout()

So, step one (kind of) accomplishes what you want:

arr.forEach(function(item) {
   timeout(3000)
      .then(() => { 
         item.a = item.a + 1; 
         newArr.push(item.a) 
      });
   });
console.log(arr[0],arr[1],arr[2], arr[3]);  
console.log(newArr);    

But notice, that immediately after completion of the forEach() call, arr and newArr have their old values. Eventually, they'll be updated. When can we use updated arr and newArr? We need to wait until the values are updated.

var promises=[]
arr.forEach(function(item) {

  promises.push(timeout(3000)
    .then(() => { 
            item.a = item.a + 1; 
            newArr.push(item.a) 
        })
    )
});

Promise.all(promises).then(() =>console.log(arr, newArr))

Collect up the promises and wait on them to all finish... then you know they are "up to date".

Solution 2:

You would do it like this:

Create a function that takes two parameters: a and arr and 'newArr' representing the array and a and newArr variables.

This function would act as a recursive function which would set a timeout and then call itself again like this:

var arr = [{a: 1}, {a: 2}, {a: 3}, {a: 4}];
var newArr = [];
var a = 0;

functionrecursiveIterator(a, arr, newArr) {
  var b = a;
  b++;
  var newerArr = newArr;
  if (b < arr.length) {
    setTimeout(function() {
      newerArr.push(arr[b].a);
      recursiveIterator(b, arr, newerArr);
    }, 1000);
  } else {
    console.log(newerArr);
  }
}

recursiveIterator(a, arr, newArr);

Solution 3:

Get Rid of the setTimeout. REPL

var newArr = [];
var arr = [{a: 1}, {a:2}, {a:3}, {a:4}];
arr.forEach(function(item) {
    item.a = item.a + 1;
    newArr.push(item.a);
});
console.log(newArr);

Solution 4:

You should make the increment before the timeout

var newArr = [];
var arr = [{a: 1}, {a:2}, {a:3}, {a:4}];
var itemsProcessed = 0;

arr.forEach(function(item) {
  setTimeout(function(){item.a = item.a+1;newArr.push(item.a);
  itemsProcessed++;
  if(itemsProcessed === arr.length) {
      console.log(newArr);
    }
  }, 3000);
});

Solution 5:

You can run your code synchronously via nsynjs:

Here is how your code may look like:

var longRunningFunction = function(ctx,timeout,val) {
    var ret={};
    setTimeout(function(){
        ret.result = val + 1;
        ctx.resume();
    },timeout);
    return ret;
};
longRunningFunction.nsynjsHasCallback = true;

functionmyFunc() {
    var newArr = [];
    var arr = [{a: 1}, {a:2}, {a:3}, {a:4}];
    for(var i=0; i<arr.length; i++) {
        var item=arr[i];
        item.a = longRunningFunction(nsynjsCtx,1000,item.a).result;
        newArr.push(item.a);
    }
    console.log(JSON.stringify(newArr));
}
nsynjs.run(myFunc,{},function() {
    console.log('done');
});

Resulting output will be printed with 4 seconds delay:

[2,3,4,5]

Post a Comment for "Javascript Code Running In Wrong Sequence"