3

当服务的所有回调都返回时,我有很多对服务的调用,最后我想将我的最终集合写入文件。有没有办法确保所有回调都完成?

for (id in idsCollection) {
    object.callService(id, function (res) {
        collection.push(res);
    });
}

filewriter.writetoFile("filename.json", JSon.Stringify(collection));

编辑:只是为了记录我正在使用带有nodeJS的cheerio。

4

8 回答 8

9

创建一个数组。每次设置回调时将某些内容推送到数组上。每次回调运行时都会弹出一些东西。检查回调函数内的数组是否为空。如果它为空,则所有回调都已完成。

于 2014-05-26T12:59:13.680 回答
3

我通常使用node-async库来处理这类事情。它可以很容易地做到你所说的:

async.each(yourArray,
    function(element, next) { 
        // this callback gets called for each element in your array
        element.doSomething(function(returnValue){
            next(returnValue) // call next when you're done
        }
    }, function(err, returnValues) {
        // when all the elements in the array are processed, this is called
        if (err) return console.log(err);
        console.log(returnValues) // this is an array of the returnValues
    });
})
于 2014-05-27T02:45:39.517 回答
2

你可以简单地计算它们。在您的情况下,您似乎已经知道会有多少回调。

var remaining = idsCollection.length; // assuming array
for (id in idsCollection) {
    object.callService(id, function (res) {
        collection.push(res);
        remaining -= 1; // decrement by 1 per callback
        // here you can check if remaining === 0 (all done)
    });
}
于 2014-05-26T13:02:59.923 回答
2

你可以使用灵活的库http://caolan.github.io/nimble/

灵活的并行示例

var _ = require('nimble');

_.parallel([
    function (callback) {
        setTimeout(function () {
            console.log('one');
            callback();
        }, 25);
    },
    function (callback) {
        setTimeout(function () {
            console.log('two');
            callback();
        }, 0);
    }
], function(){
    console.log('done')
});

输出

> two
> one
> done
于 2014-05-26T15:20:33.877 回答
2

我在这里看到了很多答案,但我希望这个解决方案仍然可以帮助某人。

为每个回调创建一个承诺,如下所示:

function funcToLoop(arg){
    return new Promise((resolve, reject) => {
        try{
            funcWithCallback(arg, (cbArg) => {
                // do your stuff
                resolve(cbArg)
            });  
        } catch (e) {
            reject(e)
        }
    });
}

然后,您可以创建一个循环作为异步函数并在此处处理最终结果/状态/等:

async function mainLoop(array){

    let results = [];

    for (let arg of array){
        results.push(await funcToLoop(arg))
    }
    // handle results
}

...或者你可以有一个同步功能,收集承诺并处理它们:

function mainLoop(array){

    let promises = [];

    for (let arg of array){
        promises.push(funcToLoop(arg))
    }
    Promise.all(promises).then(()=>{
        // handle promises
    })
}

克劳迪奥

于 2021-01-28T22:52:32.233 回答
1

如果你使用 jQuery,你可以使用$.when

例子:

exmCall1 = $.getJson(..);
exmCall2 = $.getJson(..);

$.when(exmCall1, exmCall2).done(function (exmCall1Ret, exmCall2Ret) {
    //do stuff
});

您可以在此处阅读实际文档:http: //api.jquery.com/jquery.when/

于 2014-05-26T12:58:38.007 回答
1

jQuery.Deferred()对象可能是您正在寻找的。

或者,如果您使用的是 HTML5,则可以使用promises.

这是创建承诺的方法

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

这里是如何使用它们

promise.then(function(result) {
  console.log(result); // "Stuff worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});

检查此链接以获取更多信息

于 2014-05-26T13:01:03.663 回答
0

或者做一些硬编码:

    var running;
    for (id in idsCollection) {
        object.callService(id, function (res) {
            collection.push(res);
            running += 1;
        });
    }

    var loop = setInterval(function() {
    if(running >= idsCollection.length) {
        filewriter.writetoFile("filename.json", JSon.Stringify(collection));
        clearInterval(loop);
    }
    , 500);
于 2014-05-26T13:07:29.667 回答