【问题标题】:Why does my async function return an empty array?为什么我的异步函数返回一个空数组?
【发布时间】:2020-08-30 10:16:46
【问题描述】:

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

这是我的路由器代码:

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

感谢您的帮助。

【问题讨论】:

  • 这是因为.map() 不知道async。它不会等待回调返回的承诺。您可以切换到普通的 for 循环,因为 for loop 是承诺感知的,它会正确地 await 或者您可以使用 await Promise.all(userMatchs.map(...))
  • 仅供参考,使用.map() 有点傻,但仍然手动执行matchs.push(match)。当您想要从 .map() 返回的数组时,您使用 .map(),而您完全忽略了该数组。否则,只需使用 for 循环。
  • 也许你没有看到,但我在我的回答中提供了这个信息的一个更扩展的版本,包括几个不同的实现选择。

标签: javascript node.js express mongoose async-await


【解决方案1】:

您的问题是 userMatchs.map

将 async/await 与 map() 结合使用可能有点棘手

How to use Async and Await with Array.prototype.map()

【讨论】:

    【解决方案2】:

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

    await userMatchs.map(...) 
    

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

    您可以切换到普通的 for 循环,因为 forloop 可以感知承诺并且它会正确地 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;
    }
    

    【讨论】:

      【解决方案3】:

      这段代码

      userMatchs.map(async (m) => {
          let match = await Match.findById(m._id).select([
            "-isConfirmed",
            "-isUnmatched",
          ]);
          matchs.push(match);
        }); // -> return an array of promises
      

      它返回一个promise数组,所以await不会等待它执行,->返回空数组。

      为此,您应该使用Promise.all()

      类似这样的:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-25
        • 2022-01-09
        • 1970-01-01
        • 2018-07-14
        相关资源
        最近更新 更多