0

Stack Overflow 有很多关于这个错误的问题。每一个都有它的上下文。我已尝试应用建议的大多数解决方案,但没有一个有效。我也是 koa 和 mongoose 的新手

"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) {

这意味着猫鼬保存功能正在向用户发送标头。如何解决这个问题?

4

1 回答 1

1

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

Thats where the async/await pattern comes into play. As you are already in an async function, all you need to do is await the result of .save(). You can await promises. Luckily mongoose .save() returns a promise if you are not passing a callback. That means you can just await it. so...

await newPerson.save()
ctx.render('show_message', {
    message: "New person added", type: "success", person: personInfo
})

error handling is done a little differently when using async await, or better error handling is done properly again ;-).

You'll use try/catch for error handling as you normally would in js.

try{
    await newPerson.save()
    ctx.render(...)
}catch(err){
    ctx.status=500
    ctx.body="somthing went wrong"  
}
于 2017-09-28T02:31:33.623 回答