Почему для NodeJS http-сервера не истекает бесконечный l oop? - PullRequest
0 голосов
/ 04 мая 2020

Я установил тайм-аут NodeJS http-сервера на 10 секунд:

const httpServer = require('http').createServer(app);
httpServer.timeout = 10 * 1000;

Время ожидания входящего запроса к серверу истекает через 10 с, как и ожидалось при запуске тайм-аута 20 с:

await new Promise(resolve => setTimeout(resolve, 20000));

Сервер также истекает, как и ожидалось, когда бэкэнд-запрос занимает 20 с, например:

http://httpstat.us/200?sleep=20000

Но он не срабатывает при бесконечном выполнении l oop:

while(true) {}

Почему это?

1 Ответ

2 голосов
/ 04 мая 2020

Когда вы запускаете бесконечное число l oop, никакие другие события в Javascript не могут выполняться. Событие l oop заблокировано. Таким образом, даже таймер, управляющий временем ожидания, не может работать. Это является следствием того факта, что Javascript запускает ваш JS в одном потоке, и такие вещи, как setTimeout(), являются управляемыми событиями, а не упреждающими. Итак, если вы находитесь в бесконечном l oop, то событие l oop не может обработать какие-либо события, и setTimeout() никогда не срабатывает, что обычно приводит к таймауту http.

Добро пожаловать в управляемую событиями архитектуру node.js.

И, на случай, если вам интересно, это:

while(true) {}

останавливает все другие действия в node.js тоже, не только таймеры. Единственное, что может работать, - это рабочие потоки, но они не могут даже взаимодействовать с основным потоком с заблокированным событием l oop.

К вашему сведению, вы можете продемонстрировать это для себя примерно так:

let start = Date.now();

function time() {
    let delta = (Date.now() - start) / 1000;
    return delta.toFixed(3);
}

console.log(`${time()}: Starting 500ms timer`)

// set timer for 500ms
setTimeout(() => {
   console.log(`${time()}: timer callback called`);
}, 500);

// spin for 3 seconds
while (Date.now() - start < 3000) {}

console.log(`${time()}: finished while loop`);

Вы очень четко видите, что таймер не может срабатывать, пока не закончится l oop. Хотя таймер должен срабатывать через 500 мс, он не может обработать свой обратный вызов до истечения 3 секунд, пока l oop завершено.

...