等待解决多个回调

Wait to resolve multiple callbacks

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

我目前的尝试是这样的:

  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 的所有回调。我看过使用 promises 但我不确定它究竟是如何工作的。

有谁知道如何让它发挥作用?

谢谢, 丹尼尔

你需要做异步循环,等待最终响应。你可以这样做

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);
    });
  });

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

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

您需要选择 an implementation, on which it will depend how to promisify 您的 find 方法调用。假设您有一个 find 函数,它接受接收器和选项,并且 returns 您是一个承诺 - (编辑)在猫鼬中,您很幸运并且 .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-promises 被解析(并行)的部分。