首页 > 解决方案 > 使用 promise 从 express 中间件返回并从循环中中断返回 404

问题描述

我正在尝试使用下面与被盗CarDb 对象一起使用的数据库函数从快递返回一个对象(汽车)的数组,但是数据库函数的功能非常好

执行以下操作会返回 404 错误UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

router.post("/reportstolen", function (request: express.Request, response: express.Response, next: (err?: Error) => void) {
    stolenCarDb.put_car(request.body)
        .then(() => {
            stolenCarDb.get_available_cops()
                .then(cops => {
                    cops.forEach(cop => {
                        stolenCarDb.assign_cop_car(cop._id, request.body._id)
                            .then(() => response.status(201).send(`assgined cop ${cop._id} to car`))
                    })
                })
                .then(() => response.status(201).send("created"))
        })
        .catch(() => response.status(500).send("error"))
        .finally(next)
})

标签: node.jstypescriptloopsexpresspromise

解决方案


您多次向用户发送响应,这是您无法做到的。在所有操作完成后,您应该只发送一次响应。

编辑:如果我必须自己重写代码,我会使用 async/await。您可以在此处阅读更多相关信息。

同样在重新阅读您的代码时,我看不到nextfinally块中调用的意义。

异步/等待

router.post("/reportstolen", async function (request: express.Request, response: express.Response, next: (err?: Error) => void) {
    try {
      await stolenCarDb.put_car(request.body)
      const cops = await stolenCarDb.get_available_cops(); 
      for (const cop of cops) {
        await stolenCarDb.assign_cop_car(cop._id, request.body._id);
      }

      response.status(201).send("created")
    } catch (err) {
      response.status(500).send("error")
    }
});

如果您想显示每个警察到汽车的添加,您可以执行以下操作:

router.post("/reportstolen", async function (request: express.Request, response: express.Response, next: (err?: Error) => void) {
    try {
      await stolenCarDb.put_car(request.body)
      const cops = await stolenCarDb.get_available_cops();
      for (const cop of cops) {
        await stolenCarDb.assign_cop_car(cop._id, request.body._id);
        res.write(`assgined cop ${cop._id} to car\n`);
      }

      response.status(201).send("created")
    } catch (err) {
      response.status(500).send("error")
    }
});

我还建议你阅读这篇关于在循环中使用 Promise 以及为什么你不想在循环中使用 Promise 的文章forEach


推荐阅读