Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 异步循环中的Node.js Api调用_Javascript_Node.js_Asynchronous_Foreach_Callback - Fatal编程技术网

Javascript 异步循环中的Node.js Api调用

Javascript 异步循环中的Node.js Api调用,javascript,node.js,asynchronous,foreach,callback,Javascript,Node.js,Asynchronous,Foreach,Callback,我很难进行多个api调用并在正确的位置获取返回的结果。这就是我想要实现的:两个嵌套的循环。外部循环在复杂的json对象上循环,并将一些对象的值放入数组调用框中。内部循环调用api,并将返回的结果放入名为bag的数组中。所以我有一个装满数据的盒子和袋子。当两个循环和api调用都结束时,我希望能够访问box和bag中的数据,并对其进行处理。我只是不确定在同一执行点访问两个阵列的最佳方式。这就是我到目前为止所做的,但是包和盒当然是空的,因为它们在所有循环和api调用结束之前被调用 var data =

我很难进行多个api调用并在正确的位置获取返回的结果。这就是我想要实现的:两个嵌套的循环。外部循环在复杂的json对象上循环,并将一些对象的值放入数组调用框中。内部循环调用api,并将返回的结果放入名为bag的数组中。所以我有一个装满数据的盒子和袋子。当两个循环和api调用都结束时,我希望能够访问box和bag中的数据,并对其进行处理。我只是不确定在同一执行点访问两个阵列的最佳方式。这就是我到目前为止所做的,但是包和盒当然是空的,因为它们在所有循环和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);

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

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
是上述重要部分。

既然您拥有完整的数据集,您应该首先(同步)将名称列表收集到一个数组中

然后,只执行一级
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' ]

async
是对Caolan异步库的引用吗?如果它确实是Caolan的异步库,那就不是使用它的方式。async的Github页面有很好的功能examples@BrandonTilley是的,这是lodash的Caolan的Async+1,因为我一直在使用下划线。我也认为这是一个很好的方法,但我仍然需要嵌套循环,因为我的dat非常复杂一个对象。我可以立即看到它是如何工作的。它确实起了作用。但是,我不喜欢到处都有旗帜。这个解决方案对我来说总的积极方面是习惯于在回调中思考。