web-dev-qa-db-fra.com

Node.js erreur "write after end"

En commençant avec une application de noeud de base, je ne vois pas comment vaincre cette erreur "écrire après la fin", même avec les rappels suggérés sur plusieurs sites.

index.js:

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.start(router.route, handle);

server.js:

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var postData ="";
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname, response);
   }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

routeur.js:

function route(handle, pathname, response) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname](response);
  } 
  else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;

and now the culprit, requestHandlers.js:

function start(response) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<div>Hello Start</div>' +
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response) {
    console.log("Request handler 'upload' was called");
    response.writeHead(200, {"Content-Type": "text/plain"}); 
    response.write("Hello Upload");
    response.end();
}

exports.start = start;
exports.upload = upload;

Et voici la trace de la pile:

C02RF8L7FVH5: HelloWorld francop $ node index.js Le serveur a démarré . Demande de/reçue . Sur le point de router une demande pour / Le gestionnaire de demandes 'start' s'appelait . Sur le point de router une demande pour / Le gestionnaire de demandes 'start' s'appelait . events.js: 141 lancer er; // Evénement 'erreur' non géré ^

Erreur: écrire après la fin à ServerResponse.OutgoingMessage.write (_http_outgoing.js: 430: 15) sur Object.start (/Users/francop/Documents/Apps/HelloWorld/requestHandlers.js:18:14) at route (/Users/francop/Documents/Apps/HelloWorld/router.js:5:21) à IncomingMessage. (/Users/francop/Documents/Apps/HelloWorld/server.js:19:6) at emitNone (events.js: 67: 13) à IncomingMessage.emit (events.js: 166: 7) at endReadableNT (_stream_readable.js: 921: 12) à nextTickCallbackWith2Args (node.js: 442: 9) at process._tickCallback (node.js: 356: 17)

Les seules réponses que j'ai trouvées n'importe où étaient "C'est asynchrone, utilisez un rappel" comme ceci:

response.write(body, function(err) {
    response.end();
});

... Qui jette exactement la même erreur.

Toute aide à ce sujet serait incroyable. Les quelques réponses éparses que j'ai trouvées en ligne ne m'aident pas du tout.

Merci!

7
sir_dancealot

Ceci est un exemple tiré de "The Node Beginner"

J'ai republié les fichiers ci-dessous car, à la date de publication de ce message, il n'y a pas de séparation entre votre message "routeur.js" et "requestHanders.js". 

Je rencontrais le même problème lorsque j'ai exécuté cela dans le noeud V8 qui s'exécute actuellement avec le noeud d'incident v9.5.0. Je ne présente pas cela comme une solution au problème, je dis simplement que cela a fonctionné pour moi. Peut-être que c'était un problème résolu dans la version mise à jour, je ne peux pas le dire avec certitude.

De plus, votre flux d'erreur lit "requestHandlers.js: 18: 14". Vous obtiendrez de meilleurs résultats si vous confirmez la ligne 18 figurant dans votre code (à l'avenir). Sans espaces, la ligne 18 est la ligne avant la déclaration de la fonction de téléchargement. Quand en fait cette erreur a été déclenchée par "response.end ();"

index.js

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;

server.start(router.route, handle);

routeur.js

function route(handle, pathname, response) {
  console.log("About to route a request for " + pathname);
  if (typeof handle[pathname] === 'function') {
    handle[pathname](response);
  } 
  else {
    console.log("No request handler found for " + pathname);
    response.writeHead(404, {"Content-Type": "text/plain"});
    response.write("404 Not found");
    response.end();
  }
}

exports.route = route;

server.js

var http = require("http");
var url = require("url");

function start(route, handle) {
  function onRequest(request, response) {
    var postData ="";
    var pathname = url.parse(request.url).pathname;
    console.log("Request for " + pathname + " received.");

    route(handle, pathname, response);
   }

  http.createServer(onRequest).listen(8888);
  console.log("Server has started.");
}

exports.start = start;

requestHandlers.js

function start(response) {
  console.log("Request handler 'start' was called.");

  var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<div>Hello Start</div>' +
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.write(body);
    response.end();
}

function upload(response) {
    console.log("Request handler 'upload' was called");
    response.writeHead(200, {"Content-Type": "text/plain"}); 
    response.write("Hello Upload");
    response.end();
}

exports.start = start;
exports.upload = upload;
1
Jason Smart

Renvoyez votre corps dans response.end() au lieu de response.write()

function start (response) {
    console.log("Request handler 'start' was called.");
    var body = '<html>'+
    '<head>'+
    '<meta http-equiv="Content-Type" content="text/html; '+
    'charset=UTF-8" />'+
    '</head>'+
    '<body>'+
    '<div>Hello Start</div>' +
    '</body>'+
    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});
    response.end(body);
}

Modifier 1:

La première fois que response.write() est appelé, il envoie les informations d’en-tête mises en mémoire tampon et le premier corps au client. La deuxième fois que response.write() est appelé, Node.js suppose que vous allez transmettre des données en continu et l’envoie séparément. C'est-à-dire que la réponse est mise en mémoire tampon jusqu'à la première partie du corps.

Donc, si vous voulez envoyer un seul morceau, vous devez utiliser response.end(body), et si vous voulez envoyer plusieurs morceaux, vous devez terminer l'appel avec le response.end() après plusieurs response.write().

Exemple de morceau unique:

function (chunk){
    response.end(chunk);
}

Exemple de plusieurs morceaux:

function (chunkArray){
    // loop on chunks 
    for(var i=0; i < chunkArray.length; i++){
        response.write(chunkArray[i]);                
    }

    // end the response with empty params
    response.end();
}
1
David Antoon