Nodejs: Свързване и writeHead при първото свързване-обратно извикване

Винаги получавам грешката „Грешка: Не мога да задам заглавки след изпращането им.“, когато извиквам „res.writeHead(...)“ в първото обратно извикване на свързване:

var http = require('http');
var connect = require('connect');

var simpleApp = connect();

simpleApp
    .use(function(req, res, next){

        res.writeHead(200, { 'content-type': 'text/html' });
        res.write('response powered by SIMPLE connect-object as middelware');

        console.log('Pre');
        next();
        console.log('Post');
    })
    .use(function(req, res, next){
        console.log('I am the header guy!');
        next();
    })
    .use('/admin', function(req, res, next){
        console.log('someone entered the admin area....');
        next();
    })
    .use(function(req, res){
        console.log('reached the tail of the "chain of responsibility!!!');
        res.end();
    });

http.createServer(simpleApp).listen(process.env.PORT || 3000);

console.log('Running on port "' + (process.env.PORT || 3000) + '"');

// just a save-guard to stop the process after some time...
setTimeout(function(){
    process.exit(0);
}, 20000);

И това е съобщението за грешка:

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:691:11)
    at ServerResponse.res.setHeader (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\node_modules\connect\lib\patch.js:63:22)
    at next (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\node_modules\connect\lib\proto.js:156:13)
    at Object.handle (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\connectSampleApp.js:13:3)
    at next (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\node_modules\connect\lib\proto.js:193:15)
    at Function.app.handle (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\node_modules\connect\lib\proto.js:201:3)
    at Server.app (C:\Users\drt\SkyDrive\Programmierung\nodejs\silkveil\node_modules\connect\lib\connect.js:65:37)
    at Server.EventEmitter.emit (events.js:98:17)
    at HTTPParser.parser.onIncoming (http.js:2108:12)

Когато преместя кода "writeHead" в последното обратно извикване, всичко е наред:

.use(function(req, res){
        console.log('reached the tail of the "chain of responsibility!!!');
        res.writeHead(200, { 'content-type': 'text/html' });
        res.write('response powered by SIMPLE connect-object as middelware');
        res.end();
    });

Така че въпросът ми е: Разрешено ли е само да се използва writeHead /write в последното обратно извикване, когато се използва връзка?


person thuld    schedule 14.11.2013    source източник


Отговори (2)


проверете другия въпрос. res.writeHead По принцип след res.writeHead се извиква , заглавката не може да бъде модифицирана повече, докато методът next ще се опита да промени заглавката, което ще причини изключението.

Така че можете да промените заглавката в първото извикване за свързване, но не ви е позволено да пишете тялото (res.write). Следният код трябва да работи правилно. Накратко, можете да промените заглавката, но не и да ги изчистите.

var http = require('http');
var connect = require('connect');

var simpleApp = connect();

simpleApp
    .use(function(req, res, next){
        res.statusCode = 200;
        res.setHeader( 'content-type', 'text/html' );

        console.log('Pre');
        next();
        console.log('Post');
    })
    .use(function(req, res, next){
        console.log('I am the header guy!');
        next();
    })
    .use('/admin', function(req, res, next){
        console.log('someone entered the admin area....');
        next();
    })
    .use(function(req, res){
        res.write('response powered by SIMPLE connect-object as middelware');
        console.log('reached the tail of the "chain of responsibility!!!');
        res.end();
    });

http.createServer(simpleApp).listen(process.env.PORT || 3000);

console.log('Running on port "' + (process.env.PORT || 3000) + '"');

// just a save-guard to stop the process after some time...
setTimeout(function(){
    process.exit(0);
}, 20000);
person Changgeng    schedule 14.11.2013
comment
Добре, така че е позволено да се извиква само res.write в последното обратно извикване!? Тъй като мога да използвам res.setHeader('content-type', 'text/html'); в първото обратно извикване и работи. - person thuld; 14.11.2013
comment
Добре, трябва да оставите отговора в частта Head преди последното обратно извикване. - person Changgeng; 14.11.2013
comment
Благодаря за вашият отговор - person thuld; 14.11.2013

Забравихте този ред в първата си част от кода:

res.end();

Ако това не работи, има коментар от TJ Holowaychuk тук: https://github.com/senchalabs/connect/issues/683#issuecomment-10018892

person Andrew Surzhynskyi    schedule 14.11.2013
comment
Res.end() се извиква в последното обратно извикване за свързване. Идеята ми е да пиша в отговора в различни обратни извиквания и след това да завърша отговора в последното обратно извикване и не разбирам коментара във вашата връзка... защо не е добра идея да използвате writeHead? Аз съм съвсем нов в node.js, така че ме търпете - person thuld; 14.11.2013