在阵列上推送相同的功能时调用异步功能

时间:2014-09-29 13:58:10

标签: javascript node.js promise bluebird

我有这段代码:

var queue = [];
var allParserd = [];

_.each(webs, function (web) {
    queue.push(function () {
        WebsitesUtils.parseWebsite(web, function (err, parsed) {
            allParserd.push(parsed);
        });
    });
});

Promise.all(queue).then(function (data) {
    console.log(allParserd);
});

基本上我需要获取所有的网页,并确保在每次解析完成后给出结果。函数parseWebsite返回正确的数据,但不会调用这种方式,allParsed只返回一个空数组。我确信我错过了一些事情,我已经开始使用这些承诺了。

如果您需要更多信息,请告诉我。

P.S。 我希望所有功能同时启动;我不想等待每一个回复。

3 个答案:

答案 0 :(得分:2)

用Bluebird标记,让我们使用它:

首先,让我们将您的回调API转换为承诺:

  Promise.promisifyAll(WebsitesUtils);

现在,让我们使用.map将网址中的每个项目映射到正在解析的解析网站:

Promise.map(webs, function(item){
    return WebsitesUtils.parseWebsiteAsync(item); // note the suffix
}).then(function(results){
    // all the results are here.
}).catch(function(err){
    // handle any errors
});

正如你所看到的 - 这对蓝鸟来说是微不足道的。

答案 1 :(得分:1)

Promise.all没有执行一系列函数。它需要一个 promises数组,它代表了许多同时运行(仍然未决)请求的结果。

第一步是拥有一个实际返回promise的函数,而不是只执行一个回调。我们可以使用

function parseWebsite(web) {
    return new Promise(function(fulfill, reject) {
        WebsitesUtils.parseWebsite(web, function (err, parsed) {
            if (err)
                reject(err);
            else
                fulfill(parsed);
        });
    });
}

或简单地使用promisification来执行此操作:

var parseWebsite = Promise.promisify(WebsitesUtils.parseWebsite, WebsitesUtils);

现在我们可以通过为每个站点调用该函数来构建我们的promises数组:

var promises = [];
_.each(webs, function (web) {
    promises.push(parseWebsite(web));
});

或只是

var promises = _.map(webs, parseWebsite);

这样我们最终可以使用Promise.all,然后返回我们的allParsed数组(甚至与webs的顺序相同!):

Promise.all(promises).then(function(allParsed) {
    console.log(allParsed);
});

Bluebird甚至提供快捷功能,因此您不需要promises

Promise.map(webs, parseWebsite).then(function(allParsed) {
    console.log(allParsed);
});

答案 2 :(得分:0)

以下是如何使用async

var async = require('async');

var webs = ...

async.map(webs, function(web, callback) {
  WebsitesUtils.parseWebsite(web, callback);
}, function(err, results) {
  if (err) throw err; // TODO: handle errors better

  // `results` contains all parsed results
});

如果parseWebsite()不是依赖于WebsitesUtils的原型方法,那么您可以进一步简化它:

async.map(webs, WebsitesUtils.parseWebsite, function(err, results) {
  if (err) throw err; // TODO: handle errors better

  // `results` contains all parsed results
});