如何在迭代数组时等待回调

时间:2015-09-23 21:17:24

标签: javascript arrays

我正在使用Javascript中的跨国框架。因此,在继续之前,我需要等待上一个查询完成。例如......

// Explicit this won't work because the length is not static
var i = [1,2,3]
doSomething(i[0], function(){
  doSomething(i[1], function(){
    doSomething(i[2], function(){
       commitTransaction()
    }
  })
})

从这个例子中我无法找到一种动态的方法。这感觉就像一个队列/递归问题,但我似乎无法破解它。

有没有其他人有想法?我也可以包含承诺,这也是一个选项,虽然这似乎不太同步。

3 个答案:

答案 0 :(得分:1)

使用async.eachSeries。因此,您的代码将转换为:

var transaction = {...};
async.eachSeries([1, 2, 3], function(value, callback) {
  doSomething(value, transaction, callback);
}, function(err) {
  if(err) throw err; // if there is any error in doSomething
  commitTransaction(transaction);
});

答案 1 :(得分:1)

<强> jsFiddle Demo

我建议排队做这件事。它需要数组,泛型回调函数和最终函数来回调。基本上,实现此目的的最佳方法是让您的函数期望注入值。

核心假设是,可以理解调用者将允许其回调函数具有当前值并注入下一个回调函数。这基本上意味着我们将得到一个名为queueAll的函数,它看起来像这样

function queueAll(arr,cbIteration,final){
 var queue = [function(){ cbIteration(arr[arr.length-1],final) }];
 for(var i = arr.length-2; i > 0; i--){
  (function(next,i){
   queue.unshift(function(){ cbIteration(arr[i],next) });
  })(queue[0],i)
 }
 cbIteration(arr[0],queue[0]);   
}

进行最后一次调用,将其置于队列中,然后进行迭代,将后续回调函数放入队列中,当前值关闭,并关闭队列的前端,此时该队列的下一个是下一个打回来。它使用起来相当简单。传递一个数组,一个期望值被注入的回调,以及一个最终函数。

在你的情况下,它看起来像

queueAll(i,function(item,next){
 doSomething(item,next);
},function(){
 commitTransaction(); 
});

<强> Stack Snippet Demo

//## <helper queue>

function queueAll(arr,cbIteration,final){
 var queue = [function(){ cbIteration(arr[arr.length-1],final) }];
 for(var i = arr.length-2; i > 0; i--){
  (function(next,i){
   queue.unshift(function(){ cbIteration(arr[i],next) });
  })(queue[0],i)
 }
 cbIteration(arr[0],queue[0]);   
}

//## </helper queue>

//## <user defined functions>

function doSomething(val,callback){
 setTimeout(function(){
     console.log(val);
     callback();
 },val*10);
}

function commitTransaction(){
 console.log("commit");   
}

//## </user defined functions>

//## <actual use>

var arr = [10,20,30];

queueAll(arr,function(item,next){
 doSomething(item,next);
},function(){
 commitTransaction(); 
});

//## </actual use>

答案 2 :(得分:0)

实际上,我认为承诺正是您所期待的。但对于传统的回调方法,请考虑以下因素:

var state = false,

doSomething = function (value, callback) {
    /* do stuff with value */
    if (!state)
        doSomething(newValue, callback);
    else
        callback();
};