2012-01-21 4 views
5

Если у меня есть простая функция setTimeout() и установите ее на 10 секунд ...В Node.js, setTimeout() блокирует цикл событий?

Весь сервер мертв в течение этих 10 секунд ??? Это правда? Вот что я слышал.

+1

Короткий ответ: нет. – voithos

+0

@voithos то что это? http://stackoverflow.com/questions/8949465/node-js-how-would-you-recreate-the-settimeout-function-without-it-blocking-th – TIMEX

+1

Вы прочитали ответы в этой связи? Это не 'setTimeout', который блокировал цикл событий, это была функция' wait() ', которую они реализовали. Это, буквально, просто ждало заданное количество времени (с петлей while, не менее)! Конечно, это будет блокировать. 'setTimeout' не работает. – voithos

ответ

19

Ответ нет. Какая ваша ссылка Node.js: How would you recreate the 'setTimeout' function without it blocking the event loop? показана не была setTimeout, блокируя цикл событий, это был цикл while, который намеренно блокирует цикл событий. Если вы хотите, чтобы ваш сервер был быстрым, вы не хотите блокировать цикл событий. Асинхронный обратный вызов, такой как setTimeout, будет отлично работать.

Вы пытаетесь заблокировать по какой-то причине (например, тестирование или что-то?)

+0

Кроме того, все вышеприведенное также относится к setInterval. – alessioalex

2

Это неправда. Когда вы вызываете setTimeout и возвращаете свой код, сервер не блокируется. Вы можете обрабатывать другие события (возможно, другие обратные вызовы setTimeout), ожидая, пока ваш конкретный таймер будет стрелять

2

ссылке, которую Вы, кажется, запутались делает не состояние, которое setTimeout будет блокировать. Скорее, ОП в этом вопросе пытался создать пользовательскую функцию под названием wait, которая будет вести себя как setTimeout. Функция wait является функцией блокировки - setTimeout не будет блокироваться.

4

Другое обнаружение, которое может помочь другим, которые изучают Node.js и интересуются этим вопросом, но обманом скрытого поведения современных браузеров.

Код действительно прост, я просто хочу проверить свое понимание «асинхронного характера» Node.js.

var express = require('express'); 
var router = express.Router(); 

router.get('/', function(req, res, next) { 
    console.log("route begin"); 
    var start = new Date(); 


    setTimeout(function() { 
     res.render('index', { title: start + ' - ' + new Date()}); 
    }, 20000);//force delay of 20 seconds. 

    console.log("route end"); 
}); 

module.exports = router; 

Если я начну три окна браузера (Firefox, более точно), откройте URL, определенные по этому маршруту в то же время, и проверьте журнал на консоль Node.js, то ясно, что запрос не обрабатывается одновременно!

Я попробовал тест несколько раз, результаты такие же.

Типичный выход журнала выглядит так:

route begin at: Fri Aug 28 2015 18:35:57 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:35:57 GMT+0800 (CST) 
route begin at: Fri Aug 28 2015 18:36:18 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:36:18 GMT+0800 (CST) 
route begin at: Fri Aug 28 2015 18:36:20 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:36:20 GMT+0800 (CST) 

А также, как ни странно, он не работает в последовательном режиме либо (если Node.js заблокирован SetTimeout, он должен). Интервал между первым и вторым запросами составляет 20 секунд, а второй и третий - всего 2 секунды.

После того, как я почесываю голову довольно долго, я вдруг вспоминаю, что у браузера есть ограничение на соединение на том же хосте!

Итак, я быстро настрою еще один тест, но на этот раз, выпустив несколько команд curl.

Аллилуйя!

route begin at: Fri Aug 28 2015 18:42:51 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:42:51 GMT+0800 (CST) 
route begin at: Fri Aug 28 2015 18:42:53 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:42:53 GMT+0800 (CST) 
route begin at: Fri Aug 28 2015 18:42:55 GMT+0800 (CST) 
route end at: Fri Aug 28 2015 18:42:55 GMT+0800 (CST) 
0

Основной процесс, как представляется, monothreaded хозяином и заблокирован setTimeout или while.

Тем не менее, есть альтернатива с этим кодом, который работает, как ожидалось, и не блокируют основной процесс или цикл событий:

var express = require('express') 
var app = express() 

function setTimeoutAsync (callback, time) { 
    setTimeout(function() { 
    callback() 
    }, time) 
    return 0 
} 

app.get('/', function (req, res, next) { 
    console.log("route begin") 
    var start = +new Date() 
    setTimeoutAsync(function() { 
     console.log("route done") 
     res.json({ delay: ((+new Date()) - start) + 'ms' }) 
    }, 5000) 
    console.log("route end") 
}); 

app.listen(8000) 

В терминале:

route begin // first page 
route end 
route begin // second page 
route end 
route begin // third page 
route end 
route done // first render 
route done // second render 
route done // third render 

Хорошо источники:

https://www.journaldev.com/7462/node-js-architecture-single-threaded-event-loop

https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/

Смежные вопросы