如何在async.each完成之前延迟一个承诺?

时间:2014-03-17 22:54:08

标签: javascript node.js asynchronous bluebird

如何在异步操作完成之前延迟一个承诺?我正在使用异步和蓝鸟库。一旦启动程序,done()函数就会返回一个空的或几乎为空的'masterlist'对象的错误。为什么在迭代器完成其操作之前不等待异步?

// bundler.js

var masterlist = {
   "children": []
 , "keywords": []
 , "mentions": 0
 , "name" : "newsfeed"
 , "size" : 0
}

// initialize() returns a promise with the populated masterlist
exports.initialize = function() {
  return new Promise(function(resolve, reject) {

    // pullBreakingNews() returns a promise with the breaking news articles
    nytimes.pullBreakingNews().then(function(abstracts) {

      async.map(abstracts, iterator, done);

      function iterator(item, callback) {
        alchemyapi.entities('text', item, {}, function(response) {

          // initialize each entity with masterlist
          response.entities.forEach(function(entity) {
            masterlist.children[masterlist.children.length] =
             {
                 "abstract": item
               , "children": []
               , "name": entity.text
               , "size": 0
             };
            masterlist.size += 1;
            masterlist.keywords.push(entity.text);
          });

          callback(masterlist);
        });
      };

      function done(err, results) {
        if (err) {
          console.log("ERROR: ", err);
        } else {
          resolve(results);
        }
      };

    });
  });
};

Firehose.js是调用initializer()的模块。我相信firehose首先运行,并在此过程中调用promise。 server.js => firehose.js => bundler.js => nytimes api

// firehose.js
// Compares entities to Twitter stream, counts every match
exports.aggregator = function(callback) {
  bundler.initialize().then(function(masterlist) {

    t.stream('statuses/filter', { track: masterlist.keywords }, function(stream) {

      // read twitter firehose for incoming tweets.
      stream.on('data', function(tweet) {
        var tweetText = tweet.text.toLowerCase();

        // sift through each tweet for presence of entities
        masterlist.children.forEach(function(parentObject) {

          // if the entity exists in the tweet, update counters
          if (tweetText.indexOf(parentObject.name.toLowerCase()) !== -1) {
            parentObject.size += 1;
            masterlist.mentions += 1;
            callback(masterlist);
          }

        });
      });
    });
  });
};

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

请不要混合回调和承诺,只使用其中任何一个。

// Do this somewhere else, it is only needed once
// it adds promise returning versions of all alchemy methods for you
Promise.promisifyAll(require('alchemy-api').prototype);

exports.initialize = function() {
  return nytimes.pullBreakingNews().map(function(abstract) {
    // Note that it is entitiesAsync that is a promise returning function 
    return alchemyapi.entitiesAsync('text', abstract, {}).then(function(response){
      response.entities.forEach(function(entity) {
            masterlist.children[masterlist.children.length] =
             {
                 "abstract": abstract
               , "children": []
               , "name": entity.text
               , "size": 0
             };
            masterlist.size += 1;
            masterlist.keywords.push(entity.text);
      });
    });
  }).return(masterlist);
};

你的初始化函数也没有检查它是否已经初始化

答案 1 :(得分:1)

迭代器的回调接受错误作为第一个参数。如果没有错误,你应该传递一个假值(如null),而不是masterlist

function iterator(item, callback) {
    alchemyapi.entities('text', item, {}, function(response) {

      // initialize each entity with masterlist
      response.entities.forEach(function(entity) {
        masterlist.children[masterlist.children.length] =
         {
             "abstract": item
           , "children": []
       , "name": entity.text
       , "size": 0
         };
        masterlist.size += 1;
        masterlist.keywords.push(entity.text);
      });

      callback(null, masterlist);
    });
  };