Javascript代码以错误的顺序运行

时间:2017-05-23 22:20:42

标签: javascript asynchronous callback promise

我有这样的代码:

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.push(item.a);
});
console.log(newArr);

由于异步,结果为[1,2,3,4]。让它登录[2,3,4,5]的承诺和回调方式是什么?

5 个答案:

答案 0 :(得分:2)

目前尚不清楚您是否使用超时来替换某些异步行为,或者超时是否是您尝试解决的问题的组成部分。我们两个都会找到他们。我写过关于在blog中将setTimeout()变为承诺模式的文章。因此,首先,将setTimeout()转换为基于承诺的模式:

function timeout(delay) {
    return new Promise( 
       (resolve, reject) => setTimeout( resolve, delay )
    )
} // timeout()

所以,第一步(某种程度)完成了你想要的东西:

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

但请注意,在完成forEach()来电后,arrnewArr会有旧值。 最终,它们会被更新。我们何时可以使用更新的arrnewArr?我们需要等到值更新。

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

收集承诺并等待他们全部结束......然后你知道他们是“最新的”。

答案 1 :(得分:1)

你会这样做:

创建一个带有两个参数的函数:aarr以及表示数组的'newArr'和a和newArr变量。

此函数将充当递归函数,它将设置超时,然后再次调用自身:

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

function recursiveIterator(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);

答案 2 :(得分:0)

摆脱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);

答案 3 :(得分:0)

你应该在超时前做出增量

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);
});

答案 4 :(得分:0)

您可以通过nsynjs同步运行代码:

以下是您的代码的外观:

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

function myFunc() {
    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');
});

结果输出将以4秒延迟打印:

[2,3,4,5]