2017-09-27 11 views
0

Stack Overflow contient une tonne de questions concernant cette erreur. Chacun avec son contexte. J'ai essayé d'appliquer la plupart des solutions suggérées mais aucune ne fonctionne. Je suis aussi nouveau pour Koa et mangoustesErreur: Impossible de définir les en-têtes après leur envoi à l'aide de 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") 
}) 

Lorsque j'exécute le code que je reçois l'erreur suivante:

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) 

J'ai essayé d'identifier exactement où les en-têtes sont envoyés en vous connectant sur la console quand ils sont envoyés. Comme vous pouvez le voir sur la sortie de l'erreur, les en-têtes sont envoyés immédiatement après cette ligne:

newPerson.save(function (err) { 

Ce qui signifie que la mangouste fonction d'économie est d'envoyer les en-têtes à l'utilisateur. Comment s'y prendre pour résoudre ce problème?

Répondre

1

newPerson.save() est une fonction asynchrone. Vous lui passez une fonction de rappel qui est appelée lorsque l'opération de sauvegarde est terminée. Au moment où il s'appelle cependant, votre fonction de routeur a déjà retourné et ainsi les en-têtes où déjà envoient.

Cest là où le motif asynchrone/attente entre en jeu. Comme vous êtes déjà dans une fonction asynchrone, tout ce que vous devez faire est d'attendre le résultat de .save(). Vous pouvez attendre des promesses. Heureusement, mongoose .save() renvoie une promesse si vous ne passez pas de rappel. Cela signifie que vous pouvez simplement l'attendre. alors ...

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

gestion des erreurs se fait un peu différemment lors de l'utilisation async attendent, ou une meilleure gestion des erreurs est fait correctement à nouveau ;-).

Vous utiliserez try/catch pour la gestion des erreurs comme vous le feriez normalement dans js.

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

Cela a fonctionné !! Merci beaucoup Will. Vous êtes un sauveur. J'ai presque abandonné la mangouste et je m'occupe directement de Mongodb ... –