'error' 事件在 'end' 事件之后调用?

'error' event is called after 'end' event?

const http2 = require('http2');
const fs = require('fs');
function APICall(){
    return new Promise(function(resolve,reject){
        const client = http2.connect('https://localhost:8443', {
            ca: fs.readFileSync('localhost-cert.pem')
        });
        client.on('error', (err) => console.error(err));

        const req = client.request({ ':path': '/' });

        req.on('error', (error) => {
            console.log("error",error)
            reject("Could not connect with server");
        });

        req.setEncoding('utf8');
        let data = '';
        req.on('data', (chunk) => { data += chunk; });
        req.on('end', () => {
            console.log(`\n${data}`);
            resolve(data);
        });
    });
}

我已经创建了一个 http2 客户端(使用官方网站提供的示例,除了我在 Promise 中使用它)。我遇到的问题是,即使我的服务器不可用,也会在错误事件之前调用结束事件。因此,不是错误地拒绝,而是用空数据解决承诺。我该如何解决这个问题?

所以根据 http2/core.js:

// Upon creation, the Http2Session takes ownership of the socket. The session
// may not be ready to use immediately if the socket is not yet fully connected.
// In that case, the Http2Session will wait for the socket to connect. Once
// the Http2Session is ready, it will emit its own 'connect' event.

//
// The Http2Session.goaway() method will send a GOAWAY frame, signalling
// to the connected peer that a shutdown is in progress. Sending a goaway
// frame has no other effect, however.
//
// Calling session.destroy() will tear down the Http2Session immediately,
// making it no longer usable. Pending and existing streams will be destroyed.
// The bound socket will be destroyed. Once all resources have been freed up,
// the 'close' event will be emitted. Note that pending streams will be
// destroyed using a specific "ERR_HTTP2_STREAM_CANCEL" error. Existing open
// streams will be destroyed using the same error passed to session.destroy()
//
// If destroy is called with an error, an 'error' event will be emitted
// immediately following the 'close' event.

//
// The socket and Http2Session lifecycles are tightly bound. Once one is
// destroyed, the other should also be destroyed. When the socket is destroyed
// with an error, session.destroy() will be called with that same error.
// Likewise, when session.destroy() is called with an error, the same error
// will be sent to the socket.

我认为这是预期的行为,首先流是 closed,然后发出 error

根据上述文档,我添加了一个 connect 事件以查看发生了什么。当服务器不可用时,它不会发出 connect 事件,否则它会发出。

const http2 = require('http2');
const fs = require('fs');
function APICall(){
    return new Promise(function(resolve,reject){
        const client = http2.connect('http://localhost:8443', {
            // ca: fs.readFileSync('localhost-cert.pem')
        });
        client.on('error', (err) => console.error('client error'));

        const req = client.request({ ':path': '/' });

        client.on('connect', ()=>console.log('connect'))

        req.on('error', (error) => {
            reject("Could not connect with server");
        });

        req.setEncoding('utf8');
        let data = '';
        req.on('data', (chunk) => { data += chunk; });
        req.on('end', () => {
            console.log('ended');
            console.log(`\n${data}`);
            resolve(data);
        });
    });
}

http://localhost:8443 up:

connect
ended

http://localhost:8443down:

ended
client error

因此,您可以使用 connect 事件检查是否会有 data

注:这是我看源码的看法,不知道对不对。随时编辑答案并加以改进。