【问题标题】: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,但我不确定它是如何工作的。

有谁知道如何让它工作?

谢谢你, 丹尼尔

【问题讨论】:

    标签: node.js mongodb callback mongoose 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
    猜你喜欢
    • 2017-12-15
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多