首页 > 解决方案 > 为什么我的异步函数返回一个空数组?

问题描述

我试图通过将用户推送到数组中并返回该数组来获取用户的匹配项,以便我的路由器可以将数据发送到前端。但是我的异步函数有一个问题:我只有一个空数组。我试图设置一些断点,我注意到我的路由器在我的服务将数据推送到数组之前发送了数据。

这是我的路由器代码:

router.get("/allMatchs", auth, async (req, res) => {
  const user = await userService.getUserById(req);
  const matchs = await service.getMatchsByUser(user);
  res.send(matchs);
});

还有我的服务代码:

async function getMatchsByUser(user) {
  const userMatchs = user.matchs;
  let matchs;
  await userMatchs.map(async (m) => {
    let match = await Match.findById(m._id).select([
      "-isConfirmed",
      "-isUnmatched",
    ]);
    matchs.push(match);
  });
  return matchs;
}

感谢您的帮助。

标签: javascriptnode.jsexpressmongooseasync-await

解决方案


是因为.map()没有async觉知。它不会等待回调返回的承诺。所以,当你这样做时:

await userMatchs.map(...) 

.map()返回一个数组。您正在对一系列承诺调用 await (请记住,.map()返回一个数组)。那没有任何用处。它不等待任何东西,内部的各个迭代.map()也没有等待。

您可以切换到普通for循环,因为for循环是 promise 感知的并且它会await正确,或者您可以使用await Promise.all(userMatchs.map(...)).

你可以这样做:

function getMatchsByUser(user) {
  return Promise.all(user.matchs.map((m) => {
    return Match.findById(m._id).select([
      "-isConfirmed",
      "-isUnmatched",
    ]));
  });
}

或者,如果您想一次按顺序对数据库执行一个请求,请使用一个普通for循环,该循环await适用于:

async function getMatchsByUser(user) {
  let matchs = [];
  for (let m of user.matchs) {
    let match = await Match.findById(m._id).select([
      "-isConfirmed",
      "-isUnmatched",
    ]);
    matchs.push(match);
  }
  return matchs;
}

推荐阅读