错误:使用koa发送标题后无法设置标题

时间:2017-09-27 06:08:27

标签: node.js mongodb mongoose koa koa-router

Stack Overflow对此错误有很多疑问。每个人都有其背景。我已尝试应用大多数建议的解决方案,但没有一个工作。我也是koa和猫鼬的新手

"use strict"
const Koa = require('koa')
const Router = require('koa-router')
const router = new Router()
const mongoose = require('mongoose')
const Pug = require('koa-pug')
const app = new Koa()
const KoaBody = require('koa-body')
const koaBody = new KoaBody()
mongoose.Promise = global.Promise

mongoose.connect('mongodb://localhost/my_db', {useMongoClient: true, promiseLibrary: global.Promise})

const personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
})
const Person = mongoose.model("Person", personSchema)

const pug = new Pug({
  viewPath: '.',
})

router.get('/person', async ctx => {
  ctx.render('person')
})

router.post('/person', koaBody, async (ctx, next) => {
         const personInfo = ctx.request.body
         if (!personInfo.name || !personInfo.age || !personInfo.nationality)   {
          return ctx.render('show_message', {message: "Sorry, you provided wrong info", type: "error"})
     }
     else {
         const newPerson = new Person({
             name: personInfo.name,
             age: personInfo.age,
             nationality: personInfo.nationality
         })
         if (ctx.response.headerSent) console.log("sent 0")
         newPerson.save(function (err) {
             if (ctx.response.headerSent) console.log("sent 1")
             if (err) {
                 return err
             }
             else {
                 if (ctx.response.headerSent) console.log("sent 2")
                 ctx.response.flushHeaders()
                 ctx.render('show_message', {
                     message: "New person added", type: "success", person: personInfo
                 })
             }
         })
     }
 })

pug.use(app)
app.use(router.routes())
app.listen(3000, () => {
console.log("We are listening for connections on the server")
})

当我执行代码时,我收到以下错误:

We are listening for connections on the server
sent 1
sent 2
events.js:182
  throw er; // Unhandled 'error' event
  ^

Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:504:11)
at ServerResponse.setHeader (_http_outgoing.js:511:3)
at Object.set (C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\koa\lib\response.js:440:16)
at Object.set type [as type] (C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\koa\lib\response.js:310:12)
at Object.type (C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\delegates\index.js:92:31)
at Object.contextRenderer [as render] (C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\koa-pug\src\pug.js:107:15)
at C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\learn-koa\app.js:49:25
at C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\mongoose\lib\model.js:3835:16
at C:\Users\nahas\OneDrive\Code\Javascript\Node Modules\node_modules\mongoose\lib\services\model\applyHooks.js:162:20
at _combinedTickCallback (internal/process/next_tick.js:95:7)
at process._tickCallback (internal/process/next_tick.js:161:9)

我尝试通过在发送时登录控制台来确定标头的确切位置。正如您从错误输出中看到的那样,标题会在此行之后立即发送:

newPerson.save(function (err) {

这意味着猫鼬保存功能正在向用户发送标头。 怎么办这个问题?

1 个答案:

答案 0 :(得分:1)

newPerson.save()是一个异步函数。您将回调函数传递给它,在保存操作完成时调用该函数。然而,当它被调用时,您的路由器功能已经返回,因此已经发送的头部已经发送。

这是异步/等待模式发挥作用的地方。由于您已经处于异步功能中,所以您需要做的就是等待.save()的结果。你可以等待承诺。幸运的是,如果你没有通过回调,mongoose .save()会返回一个承诺。这意味着你可以等待它。所以...

await newPerson.save()
ctx.render('show_message', {
    message: "New person added", type: "success", person: personInfo
})
使用异步等待时,错误处理有点不同,或者再次正确完成错误处理;-)。

您将像在js中一样使用try / catch进行错误处理。

try{
    await newPerson.save()
    ctx.render(...)
}catch(err){
    ctx.status=500
    ctx.body="somthing went wrong"  
}