0

我正在尝试使用以下代码检索 2 个项目的信息和每个项目(a、b、c)的用户信息。但是我遇到了一个问题,它显示重复的结果和意外的输出。

  • 查找项目 a
  • 查找用户 a
  • 查找用户 a
  • 查找项目 c
  • 查找用户 c
  • 结果
  • 查找项目 b
  • 查找用户 b
  • 结果
  • 查找用户 b
  • 结果

(“c”项只有 1 项)

我希望只看到一次结果。

var results = [];
var items = ['a', 'b', 'c']; 

function async(item, callback) {        
  findSomething(2, item, function(err, items){
    if (err) throw err; 
    console.log('findItem ' + item);
    var item = [];
    _.map(items, function(value, key) {
      findSomethingElse(items[key].id, function(err, name){
        if(err) throw err;
        console.log('findUser ' + item);
        item['name'] = name;            
        item['items'] = items[key];            
        callback(item);
      });  
    });      
  });
} 

function final() { 
  console.log('results');
  // return results;
}

function series(item) {
  if(item) {
    async(item, function(result) {
      results.push(result);
      return series(items.shift());
    });
  } else {
    return final();
  }
}
series(items.shift());

正如建议的那样,我尝试使用 async 模块并让此代码正确显示项目和用户,但我不确定如何进行回调以在 done() 函数中显示结果数组。

var results = [];
var items = ['a', 'b', 'c']; 

async.each(items, findItem, function(err){
  if(err) throw err;
}); 

function findItem(item) { 
  Bid.findBids(2, item, function(err, bids){
    if (err) throw err; 
    async.each(bids, findUser, function(err){
      if(err) throw err;
    });
  });
}

function findUser(item) {
  User.findBidder(item.email, function(err, user){
    if(err) throw err;
    var bid = [];
    bid['user'] = user;            
    bid['item'] = item;           
    results.push(bid);
  });
}    

function done() { 
  console.log('Results: ' + results);
  return results;
}
4

1 回答 1

0

这是使用异步队列的可能解决方案:

var results = [];
var items = ['a', 'b', 'c']; 

// We assume items[] isn't empty, and create a queue
// to process each item.
var itemQueue = async.queue(function (item, nextItem) {
  // For each item get the bids
  Bid.findBids(2, item, function(err, bids){
    if (err) throw err; 

    // If no bids go to next item
    if (bids.length === 0) {
      nextItem();
    } else {
      // Otherwise loop through bids with another queue
      var bidQueue = async.queue(function (bid, nextBid) {
        User.findBidder(item.email, function(err, user){
          if(err) throw err;
          var bid = [];
          bid['user'] = user;            
          bid['item'] = item;     
          results.push(bid);
          nextBid();
        });
      });

      // When all bids are done, go to next item.
      bidQueue.drain = function() {
        nextItem();
      };

      // place all bids on the queue for this item.
      bidQueue.push(bids);
    }
  });
});

// When all items are done, print the results
itemQueue.drain = function () {
  console.log('Results: ');
  console.log(results);
}

// push all the items onto the queue - note that if items is 
// empty, drain() will never be called!
itemQueue.push(items);
于 2013-10-10T01:24:44.937 回答