等待解决多个回调

Posted

技术标签:

【中文标题】等待解决多个回调【英文标题】:Wait to resolve multiple callbacks 【发布时间】:2015-05-30 04:06:54 【问题描述】:

我正在尝试从与猫鼬的一次通话中获取 ID。之后,这些 ID 中的每一个都用于进行另一个返回多个对象的调用。我正在尝试获取所有这些对象。

我目前的尝试看起来像这样:

  var members;
  var memberTimes = [];

  // Use the Group model to find a specific group
  Group.find(
    members: 
      $elemMatch: 
        $eq: req.user._id
      
    ,
    _id: req.params.group_id
  , function(err, group) 
    if (err) 
      res.send(err);
     else if (!group) 
      //res.send(new Error("User not in group or it does not exist"));
    

    members = group[0].members;

    for (var member of members) 
      // Use the Time model to find a specific time
      Time.find(
        user_id: member
      , function(err, times) 
        if (err) 
          res.send(err);
        

        for (var time of times) 
          memberTimes.push(time);
        
      );
    
    //on completion of all above code, execute res.json(memberTimes);
 );

但是,这不起作用,因为我没有等待来自 Time#find 的所有回调。我看过使用 Promise,但我不确定它是如何工作的。

有谁知道如何让它工作?

谢谢你, 丹尼尔

【问题讨论】:

【参考方案1】:

您需要进行异步循环并等待最终响应。你可以做类似的事情

var members;

function getTimes(mTimes, times, i, done) 
    console.log("time " + i);
    if (i < times.length) 
      console.log(times[i]);
      mTimes.push(times[i]);
      getTimes(mTimes, times, i + 1, done);
     else 
      done(mTimes);
    
  

  function asyncLoop(memberTimes, members, i, callback) 
    if (i < members.length) 
      Time.find(
        user_id: members[i]
      , function(err, times) 
        if (err) 
          res.send(err);
        
        console.log(times);
        getTimes(memberTimes, times, 0, function(result) 
          asyncLoop(memberTimes, members, i + 1, callback);
        );
      );
     else 
      callback(memberTimes);
    
  

  // Use the Group model to find a specific group
  Group.find(
    members: 
      $elemMatch: 
        $eq: req.user._id
      
    ,
    _id: req.params.group_id
  , function(err, group) 
    if (err) 
      res.send(err);
     else if (!group) 
      //res.send(new Error("User not in group or it does not exist"));
    

    members = group[0].members;

    var memberTimes = [];
    asyncLoop(memberTimes, members, 0, function(memberTimes) 
      res.json(memberTimes);
    );
  );

上面的代码可能无法运行,因为我没有运行它,但这是你可以实现你想要的。

【讨论】:

谢谢,我会试试这个。这是解决这类问题的推荐方法吗? @DVassilev 我并不是说这是一种推荐的方式,而是一种创建异步循环的方式。 我建议进行修改以修复您的代码。谢谢。【参考方案2】:

是的,applying promises 听起来是个好主意。

您需要选择an implementation,它将取决于how to promisify 您的find 方法调用。假设您有一个 find 函数,它接受接收者和选项并向您返回一个承诺 - 在猫鼬中(编辑),您很幸运,.exec() 似乎已经产生了一个承诺:

function find(model, options) 
  return model.find(options).exec();

那么您的代码将如下所示:

find(Group, 
  members: $elemMatch: $eq: req.user._id,
  _id: req.params.group_id
).then(function(group) 
  if (!group)
    throw new Error("User not in group or it does not exist");

  return Promise.all(group[0].members.map(function(member) 
    return find(Time, user_id: member);
  ));
).then(function(memberTimes) 
  res.json(memberTimes);
, function(err) 
  res.send(err);
);

这里,Promise.all 是它等待直到解决多个 time-find-promise 的部分(并行)。

【讨论】:

感谢@DVassilev 提供find 功能,尽管评论比建议编辑要好(对大多数评论者来说,它确实改变了很多)。 没问题,很抱歉。您的代码也有一个小错误,所以我建议使用更正的版本进行编辑。谢谢你。 @Bergi

以上是关于等待解决多个回调的主要内容,如果未能解决你的问题,请参考以下文章

面试题 | 等待多个并发结果有哪几种方法?

解决回调函数

promise解决回调地狱

如何等待 requestLocationUpdates() 回调意图完成?

多个属性监听器等待两者触发回调

异步等待 Jquery ajax 回调?