我很难进行多次api调用并将返回的结果放在正确的位置。这就是我想要实现的:两个循环,嵌套。外部循环遍历复杂的json对象,并将一些对象的值放在数组调用框中。内部循环调用api并将返回的结果放在名为bag的数组中。所以我的盒子和包里装满了数据。当循环和api调用都结束时,我希望能够访问盒子和包中的数据并使用它进行操作。我只是不确定在执行的同一点上访问两个数组的最佳方法。这是我到目前为止所拥有的,但当然包和盒子都是空的,因为它们在所有循环和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 :(得分: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();
});
}
count
和onCompletion
是上述重要部分。
答案 1 :(得分:3)
由于您拥有完整的数据集,因此您应该首先(同步)将名称列表收集到一个数组中。
然后,只做一级async.forEach
。尝试使用两个级别执行此操作是不必要的,并且会导致更复杂的代码。
如果您使用async
获得的是npm install async
,那么这里有一段代码可以说明您可以使用的内容(使用lodash
来构建名称列表,因为这往往更加明确。
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' ]