событие 'error' вызывается после события 'end'? - PullRequest
1 голос
/ 01 июля 2019
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). У меня проблема в том, что даже когда мой сервер недоступен, событие end вызывается перед событием ошибки. Таким образом, вместо отказа с ошибкой, обещание разрешается с пустыми данными. Как мне решить эту проблему?

1 Ответ

1 голос
/ 01 июля 2019

Итак, согласно http2/core.js:

// После создания Http2Session становится владельцем сокета. Сессия
// может быть не готов к немедленному использованию, если сокет еще не полностью подключен.
// В этом случае Http2Session будет ожидать подключения сокета. После
// Http2Session готов, он отправит свое собственное событие 'connect'.

//
// Метод Http2Session.goaway () отправит кадр GOAWAY, сигнализируя
// к подключенному узлу, что происходит отключение. Отправка на рассылку
// кадр не имеет другого эффекта, однако.
//
// Вызов session.destroy () немедленно прервет Http2Session,
// делая его больше не пригодным для использования. Ожидающие и существующие потоки будут уничтожены.
// Связанный сокет будет уничтожен. Как только все ресурсы будут освобождены,
// событие close будет выдано. Обратите внимание, что ожидающие потоки будут
// уничтожено с помощью определенной ошибки «ERR_HTTP2_STREAM_CANCEL». Существующий открытый
// потоки будут уничтожены с использованием той же ошибки, что передана для session.destroy ()
//
// Если destroy вызывается с ошибкой, генерируется событие error
// сразу после события 'close'.

//
// Сокеты и жизненные циклы Http2Session тесно связаны. Однажды
// уничтожен, другой также должен быть уничтожен. Когда розетка разрушена
// с ошибкой session.destroy () будет вызван с той же ошибкой.
// Аналогично, когда session.destroy () вызывается с ошибкой, та же самая ошибка
// будет отправлен в сокет.

Я думаю, что это ожидаемое поведение, когда сначала поток 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 было вверх :

connect
ended

Когда http://localhost:8443 было вниз :

ended
client error

Таким образом, вы можете проверить с помощью события connect, будет ли data или нет.

Примечание: это мое мнение, читая исходный код, я не знаю, правильно ли это или нет. Не стесняйтесь редактировать ответ и улучшать его.

...