【问题标题】:Unhandled promise error in Node and ExpressNode 和 Express 中未处理的 promise 错误
【发布时间】:2021-05-27 21:24:15
【问题描述】:

我正在使用 NodeJS、ExpressJS 和 Mongoose 制作 CRUD API,在执行以下代码时,第 29 行出现 UnhandledPromiseRejectionWarning 错误。尽管有一个 try-catch 块。

代码:

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
require('../src/db/conn.js');
const MensRanking = require('../src/models/mens.js');
app.use(express.json());
app.get('/', async (req, res) =>{
    res.send("<h1>Hello World!</h1>");
})

app.post('/mens', async (req, res) =>{
    try{
        const addingMensRecords = new MensRanking(req.body);
        console.log(req.body);
        const insert = await addingMensRecords.save();
        res.sendStatus(201).send(insert);
    }
    catch(e){
        res.sendStatus(400).send(e);
    }
})  

app.get('/mens', async (req, res) =>{
    try{
        const getMens = await MensRanking.find({});
        res.sendStatus(201).send(getMens);
    }
    catch(e){
        res.sendStatus(400).send(e);
    }
})

app.listen(port,()=>{
    console.log(`\nlistening at http://127.0.0.1:${port}\n`);
})

错误:

(node:20016) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:518:11)
    at ServerResponse.header (D:\projects\rest-api-sections\rest-tute\node_modules\express\lib\response.js:771:10)
    at ServerResponse.contentType (D:\projects\rest-api-sections\rest-tute\node_modules\express\lib\response.js:599:15)
    at ServerResponse.sendStatus (D:\projects\rest-api-sections\rest-tute\node_modules\express\lib\response.js:357:8)
    at D:\projects\rest-api-sections\rest-tute\src\app.js:29:13
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:20016) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:20016) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Here is the complete code repository

【问题讨论】:

  • 错误消息“在将标头发送到客户端后无法设置标头”似乎是自描述的。您正在尝试设置标头,但您已经将响应发送到 che 客户端。
  • “一、二、三、四、五……”说真的,人们不会数到 29 来帮助你。告诉我们第 29 行是哪一行! :-)
  • 尝试使用res.statusres.setStatus 而不是sendStatus
  • “尽管有一个 try-catch 块。” catch 块中的代码可能会引发错误。这将拒绝它所在的 async 函数的承诺,该代码中的任何内容都不会处理它。请记住:catch 块中的代码就是代码。这是async 函数回调传递给无法处理承诺的事物(在本例中为Express)的原因之一。

标签: javascript node.js express mongoose


【解决方案1】:

您应该使用res.status 而不是sendStatus

Difference between response.status() vs. response.sendStatus() in express

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
require('../src/db/conn.js');
const MensRanking = require('../src/models/mens.js');
app.use(express.json());
app.get('/', async (req, res) => {
  res.send('<h1>Hello World!</h1>');
});

app.post('/mens', async (req, res) => {
  try {
    const addingMensRecords = new MensRanking(req.body);
    console.log(req.body);
    const insert = await addingMensRecords.save();
    res.status(201).send(insert);
  }
  catch (e) {
    res.status(400).send(e);
  }
});

app.get('/mens', async (req, res) => {
  try {
    const getMens = await MensRanking.find({});
    res.status(201).send(getMens);
  }
  catch (e) {
    res.status(400).send(e);
  }
});

app.listen(port, () => {
  console.log(`\nlistening at http://127.0.0.1:${port}\n`);
});

【讨论】:

    【解决方案2】:

    您正在使用 epxress.js 的 sendStatus 函数,因为它会立即将特定分配的代码发送到响应对象,该对象在设置数据之前触发响应,因此当您的 send 函数被调用时,响应对象已经发送,因此错误:

    标头发送到客户端后无法设置

    相反,当您需要设置 HTTP 响应代码以及数据时使用它

    res.status(RESPONSE_CODE).send(DATA)
    

    【讨论】:

      【解决方案3】:

      在这种情况下有两个有问题的函数我只强调一个,因为它们有相同的错误:

      app.post('/mens', async (req, res) =>{
      try{
          const addingMensRecords = new MensRanking(req.body);
          console.log(req.body);
          const insert = await addingMensRecords.save();
          res.sendStatus(201).send(insert);
      }
      catch(e){
          res.sendStatus(400).send(e);
      }})  
      
      1. 您已经在 try-block 中使用 res.sendStatus(201) 发送了响应,并尝试使用 .send(insert) 再次发送 -> 引发异常
      2. 之后,您再次使用 res.sendStatus(400).send(e); 执行相同的错误;

      下面的代码应该能达到你想要的效果:

      app.post('/mens', async (req, res) =>{
      try{
          const addingMensRecords = new MensRanking(req.body);
          console.log(req.body);
          const insert = await addingMensRecords.save();
          res.status(201).send(insert);
      }
      catch(e){
          res.status(400).send(e);
      }})  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-23
        • 2021-02-19
        • 2014-12-15
        • 2019-01-27
        相关资源
        最近更新 更多