6

http.request を使用してクライアント リクエスト (ノード v0.6.18、v0.6.3) を作成するとエラーが発生しました。次のコードでエラーが発生し、いくつか質問があります。

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

http.createServer(function(req, res) {
    var data = '多情自古空余恨';
    res.writeHead(200, {
        'Content-Type': 'text/plain',
        'Content-Length': 1 //ERROR
    });
    res.end(data);
}).listen(3000);

function request(options, callback) {
    var req = http.request(options, function(res) {
        var data = '';
        res.setEncoding = 'utf8';
        res.on('data', function(chunk) {
            data += chunk;
        });
        res.on('error', function(err) {
            callback(new Error('res error: ' + err));
        });
        res.on('end', function() {
            console.log('res on end');
            callback(null, data);
        });
    });
    req.on('socket', function(socket) {
        socket.on('error', function(err) {
            console.log('socket on error');
            callback('socket error: ' + err);
            req.abort();
        });
    });
    req.end();
}

request({
    host: 'localhost',
    port: 3000,
    method: 'GET'
}, function(err, data) {
    console.log('result, err: ' + err + ', data: ' + data);
});

出力:

res on end
result, err: null, data: �
socket on error
result, err: socket error: Error: Parse Error, data: undefined

ここに私の質問があります:

  1. res の「end」イベントが socket の「error」イベントよりも前に発生したのはなぜですか?
  2. 上記のコードのように、または他の状況で「ソケット.ondata での解析エラー」が発生したときにエラーをコールバックしたい場合は、上記の出力のように 2 回ではなく 1 回コールバックする方法 (IF res の「終了」イベントが実際に以前に発生した場合)ソケットの「エラー」イベント)?

あなたの助けが必要です!ありがとう。

===============================

同じコード出力が見つかりました:

res on end
result, err: null, data: �

ノード v0.6.6 および v0.6.11 で。なんで?

4

1 に答える 1

2

content-lengthヘッダーが1であるため、がrequest正確に1オクテットのデータを受信すると、それがすべてであると想定し、endコールバックを起動します。その後、ソケットが何をすべきかわからないというデータがさらに受信されるため、エラーが発生します。

これを回避するには、コールバックを起動して成功するまで少し待って、起動されたかどうかを追跡します。例えば:

var req = http.request(options, function(res) {

    var data = '';
    res.setEncoding = 'utf8';
    res.on('data', function(chunk) {
        data += chunk;
    });
    res.on('error', function(err) {
        if(!callback.called) { // check before firing the callback
          callback(new Error('res error: ' + err));
          callback.called = true; // set after firing the callback
        } // ..
    });
    res.on('end', function() {
        process.nextTick(function() { // use setTimeout if nextTick is too short
          if(!callback.called) { //..
            console.log('res on end');
            callback(null, data);
            callback.called = true; // ..
          } // ..
        }); // ..
    });
});
req.on('socket', function(socket) {
    socket.on('error', function(err) {
        if(!callback.called) { // ..
          console.log('socket on error');
          callback('socket error: ' + err);
          callback.called = true; // ..
        } // ..
        req.abort();
    });
});
req.end();

(すべての新しい行の後にコメントを追加して、少し目立たせるようにしました。)

于 2012-05-31T21:40:04.533 に答える