首页 > 解决方案 > 需要帮助来了解如何解决嵌套在多个猫鼬查询和映射数组中的承诺

问题描述

router.get('/pictures', (req, res, next) => {
  Picture.find()
  .then(handle404)
  .then(pictures => {
    return pictures.map(picture => picture.toObject())
  })
  .then(pictures => {
    pictures.map(picture => {
      User.findById(picture.owner)
      .then(owner => {
        picture.ownerName = owner.username
        console.log(pictures, "my picture with owner")
        return pictures
      })
      .then(pictures => res.status(200).json({ pictures: pictures }))
    })
  })
  .catch(next)
})
})

按操作顺序:我需要找到所有图片,然后遍历图片数组并找到所有者的用户名,然后使用所有者用户名在图片数组中添加一个键,然后使用新的图片数组发送响应包括所有者的用户名

我想返回带有找到的所有者名称的图片数组..但是在设置所有者名称之前发送响应时遇到问题,我不确定如何让响应等待。如果只有一个所有者的名字很好,但不止一个,我得到一个错误 -

UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

我认为这意味着我的回复是在我的查询完成之前发送的。

标签: mongoosepromiserequest-promise

解决方案


在循环中使用异步操作进行循环时,您必须对循环进行排序,await或者对于并行操作,将循环中的所有 Promise 收集到一个数组中,并使用它Promise.all()来跟踪它们何时完成。这是一种方法:

router.get('/pictures', (req, res, next) => {
    Picture.find()
        .then(handle404)
        .then(pictures => {
            pictures = pictures.map(picture => picture.toObject());
            return Promise.all(pictures.map(picture => {
                return User.findById(picture.owner).then(owner => {
                    picture.ownerName = owner.username
                    return picture;
                });
            }));
        }).then(pictures => {
            res.status(200).json({ pictures });
        }).catch(next);
});

此外,当您在.then()处理程序中进行异步操作时,请确保返回这些承诺,以便将它们链接到链中。


您收到的警告UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client是因为您尝试向同一个 http 请求发送多个响应。这发生在您尝试res.json(...)在循环内(因此多次)执行的循环内。避免这种情况的方法是从循环中收集结果(Promise.all()在这种情况下使用),然后在最后发送一个响应。


推荐阅读