2013-03-02 109 views
4

我很难做出多个API调用,并在正确的位置获取返回的结果。这是我想要实现的:两个循环,嵌套。外层循环遍历复杂的json对象,并将一些对象的值放入数组调用框中。内部循环调用API并将返回的结果放入一个名为bag的数组中。所以我有箱子和袋子里装满了数据。当两个循环和api调用都结束时,我希望能够访问盒子和包中的数据,并使用它进行操作。我只是不确定要在同一点执行时访问这两个数组的最佳方式。这是我迄今为止,但袋和框当然是空的,因为它们在所有循环和api调用结束之前被调用。Node.js Api调用异步循环

var data = {}//a json object with data; 
var bag = []; 
var box = []; 

async.forEach(data.item, function(item, callback){ 

    async.forEach(item.name, function(name, callback){ 

     callApi(item.name, function(obj){ 

      bag.push(obj); 
     }); 

     callback(); 

    } 

    box.push(item); 
    callback(); 

}); 


function callApi(name, callback){ 

    asyncApiCall(url+name, function(err, result){ 

     callback(result);  
    }); 

} 

//when all loops and api requests are done 
//do stuff with contents of box and bag here; 
console.log(bag, box); 
+0

是'async' – 2013-03-02 05:19:03

+1

到Caolan的异步库的引用如果是Caolan”异步的确,它不使用它的方式异步GitHub的页面具有良好例子 – Greg 2013-03-02 06:37:58

+0

@BrandonTilley是它的Caolan的异步 – Kunle 2013-03-04 16:41:12

回答

4

您可以使用计数器确保所有异步调用已返回,然后调用回调。一个例子:

function performAsyncOperation(data, onCompletion) { 
    var bag = []; 
    var box = []; 
    var count = 0; 

    async.forEach(data.item, function(item, callback){ 
     async.forEach(item.name, function(name, callback){ 
      count += 1; 
      callApi(item.name, function(obj){ 
       bag.push(obj); 
       count -= 1; 
       if (count == 0) { 
        onCompletion(null, { bag:bag, box:box }); 
       } 
      }); 
      callback(); 
     } 
     box.push(item); 
     callback(); 
    }); 
} 

countonCompletion和高于重要的部分。

+0

我可以看到这将如何立即工作。它确实奏效。但是,我不喜欢到处都有旗帜。对我来说,这个解决方案的整体积极方面是习惯于在回调中思考。 – Kunle 2013-03-04 16:40:32

3

由于您拥有完整的数据集,因此您应该首先(同步地)将名称列表收集到一个数组中。

然后,只能做一个级别的async.forEach。试图用两个级别做到这一点是不必要的,并导致更复杂的代码。

如果称其为async的就是你使用npm install async什么,这里有一段代码,说明你可以使用的(使用lodash构建名称列表,因为这往往是更consise。

var _ = require("lodash"); 
var async = require("async"); 

var data = { 
    item: [ 
    {name: "a"}, 
    {name: "b"} 
    ] 
}; 

var bag = []; 

var items = _(_(data.item).collect(function(item) { 
    return item.name; 
})).value(); 

async.eachSeries(items, function(name, cb) { 
    callApi(name, function(obj) { 
    bag.push(obj); 
    cb(); 
    }); 
}, function done() { 
    console.log("bag", bag); 
}); 

function callApi(name, cb) { 
    cb(name); 
} 

,输出为:?

bag [ 'a', 'b' ] 
+0

lodash的+1,因为我一直在使用下划线。另外我认为这是一个好方法,但由于数据对象的复杂性,我仍然需要嵌套循环。 – Kunle 2013-03-04 16:38:28