Какой быстрый способ отправить ответ клиенту и затем выполнить длинные / тяжелые действия в nodejs - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь выяснить, каков наилучший / быстрый способ отправить ответ от expressjs, а затем сделать запись или выполнить длинные действия на сервере, не задерживая ответ клиенту.

У меня есть следующий код, но я вижу, что ответ клиенту отправляется только после завершения цикла. Я думаю, что ответ будет отправлен, потому что я запускаю res.send(html); и затем звоню longAction

function longAction () {
    for (let i = 0; i < 1000000000; i++) {}
    console.log('Finish');
}

function myfunction (req, res) {
    res.render(MYPATH, 'index.response.html'), {title: 'My Title'}, (err, html) => {
        if (err) {
            re.status(500).json({'error':'Internal Server Error. Error Rendering HTML'});
        }
        else {
            res.send(html);
            longAction();            
        }
    });
}


router.post('/getIndex', myfunction);

Как лучше всего отправить ответ, а затем выполнить мои длинные / тяжелые действия? Или чего мне не хватает?

Ответы [ 3 ]

0 голосов
/ 27 апреля 2018

Использовать setImmediate:

var test = function(){
    for (let i = 0; i < 1000000000; i++) {}
    console.log('Finish');
}

router.get("/a", function(req, res, next){
    setImmediate(test);
    return res.status(200).json({});
});

Ваша длинная функция будет выполнена в конце текущего цикла цикла событий. Этот код будет выполняться после любых операций ввода-вывода (в этом примере первой операцией ввода-вывода является res.status (200)) в текущем цикле событий и перед любыми таймерами, запланированными для следующего цикла событий.

0 голосов
/ 29 апреля 2018

Спасибо за ответы:

После проверки я думаю, что лучший подход - это прослушивание finish события

res.on('finish', () => {
    // Do another stuff after finish got the response
});
0 голосов
/ 27 апреля 2018

Я пытаюсь выяснить, каков наилучший / быстрый способ отправить ответ от expressjs, а затем выполнить лог или выполнять длинные действия на сервере, не задерживая ответ клиенту.

Лучший способ сделать это - позвонить по номеру longAction() только тогда, когда экспресс сообщит вам, что ответ отправлен. Поскольку объект ответа является потоком, вы можете использовать событие finish в этом потоке, чтобы узнать, когда все данные из потока были сброшены в базовую ОС.

Из документации для записи потока :

Событие finish заканчивается после вызова метода stream.end (), и все данные сбрасываются в базовую систему.

Вот как вы можете использовать это в вашем конкретном коде:

function myfunction (req, res) {
    res.render(MYPATH, 'index.response.html'), {title: 'My Title'}, (err, html) => {
        if (err) {
            res.status(500).json({'error':'Internal Server Error. Error Rendering HTML'});
        }
        else {
            res.on('finish', () => {
                longAction();            
            });
            res.send(html);
        }
    });
}

Для более подробного объяснения события finish вы можете начать с просмотра Express-кода для res.send() и увидеть, что в итоге вызывается res.end() для фактической отправки данных. Если вы затем посмотрите на документацию для .end() в потоке для записи, он скажет следующее:

Вызов метода writable.end () сигнализирует о том, что в Writable больше не будут записываться данные. Необязательные аргументы блока и кодирования позволяют записать один последний дополнительный блок данных непосредственно перед закрытием потока. Если предусмотрено, дополнительная функция обратного вызова присоединяется в качестве прослушивателя для события финиша.

Итак, так как Express не предоставляет доступ к обратному вызову, который предлагает .end(), мы просто слушаем событие finish, чтобы получить уведомление, когда поток завершит отправку своего последнего бита данных.


Обратите внимание, в вашем коде также есть опечатка, где re.status(500) должно быть res.status(500).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...