В чем разница между этими двумя и когда я буду использовать одно вместо другого?
В чем разница между этими двумя и когда я буду использовать одно вместо другого?
Ответы:
setTimeout - это просто вызов функции после завершения задержки. Всякий раз, когда вызывается функция, она не выполняется немедленно, а ставится в очередь, так что она выполняется после того, как все выполняющиеся и находящиеся в данный момент обработчики событий завершают работу первыми. setTimeout (, 0) по сути означает выполнение после выполнения всех текущих функций в текущей очереди. Нет никаких гарантий относительно того, сколько времени это может занять.
setImmediate в этом отношении аналогичен, за исключением того, что он не использует очередь функций. Он проверяет очередь обработчиков событий ввода-вывода. Если все события ввода-вывода в текущем снимке обработаны, выполняется обратный вызов. Он ставит их в очередь сразу после последнего обработчика ввода-вывода, что-то вроде process.nextTick. Так быстрее.
Также (setTimeout, 0) будет медленным, потому что он проверит таймер хотя бы один раз перед выполнением. Иногда это может быть вдвое медленнее. Вот эталон.
var Suite = require('benchmark').Suite
var fs = require('fs')
var suite = new Suite
suite.add('deffered.resolve()', function(deferred) {
deferred.resolve()
}, {defer: true})
suite.add('setImmediate()', function(deferred) {
setImmediate(function() {
deferred.resolve()
})
}, {defer: true})
suite.add('setTimeout(,0)', function(deferred) {
setTimeout(function() {
deferred.resolve()
},0)
}, {defer: true})
suite
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})
.run({async: true})
Выход
deffered.resolve() x 993 ops/sec ±0.67% (22 runs sampled)
setImmediate() x 914 ops/sec ±2.48% (57 runs sampled)
setTimeout(,0) x 445 ops/sec ±2.79% (82 runs sampled)
Первый дает представление о максимально быстрых звонках. Вы можете сами проверить, вызывается ли setTimeout вдвое реже, чем other. Также помните, что setImmediate будет адаптироваться к вызовам вашей файловой системы. Так что под нагрузкой он будет работать меньше. Я не думаю, что setTimeout может стать лучше.
setTimeout - ненавязчивый способ вызова функций через некоторое время. Это как в браузере. Возможно, он не подходит для серверной части (подумайте, почему я использовал benchmark.js, а не setTimeout).
Отличная статья о том, как работает цикл событий, и устраняет некоторые заблуждения. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Цитирование статьи:
setImmediateобратные вызовы вызываются после завершения или истечения времени ожидания обратных вызовов очереди ввода-вывода. Обратные вызовы setImmediate помещаются в очередь проверки, которые обрабатываются после очереди ввода-вывода.
setTimeout(fn, 0)обратные вызовы помещаются в очередь таймера и будут вызываться после обратных вызовов ввода-вывода, а также обратных вызовов очереди проверки. В качестве цикла обработки событий сначала обрабатывайте очередь таймера на каждой итерации, поэтому какая из них будет выполнена первой, зависит от того, на какой фазе находится цикл событий.
setImmediate () предназначен для планирования немедленного выполнения обратного вызова после обратных вызовов событий ввода-вывода и до setTimeout и setInterval.
setTimeout () предназначен для планирования выполнения одноразового обратного вызова после задержки в миллисекундах.
Об этом говорится в документах.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
Если вы запустите приведенный выше код, результат будет таким ... даже несмотря на то, что в текущем документе указано, что «запланировать« немедленное »выполнение обратного вызова после обратных вызовов событий ввода-вывода и перед setTimeout и setInterval». ..
Результат ..
setTimeout
setImmediate
Если вы поместите свой пример в другой таймер, он всегда будет печатать setImmediate, за которым следует setTimeout.
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
всегда используйте setImmediate, если вы действительно не уверены, что вам нужно setTimeout(,0)(но даже не представляю, зачем). setImmediateобратный вызов почти всегда будет выполняться раньше setTimeout(,0), за исключением случаев, когда он вызывается в первом тике и в setImmediateобратном вызове .
setTimeoutследует setImmediateиспользовать только тогда, когда показано, что это необходимо.
Совершенно не удовлетворен предоставленными ответами. Я опубликовал здесь то, что, по моему мнению, лучше: qaru.site/questions/435 / ...
Вопросы - это возможный дубликат вопроса Почему поведение setTimeout (0) и setImmediate () не определено при использовании в основном модуле?
Я думаю, что ответ Navya S неверен , вот мой тестовый код:
let set = new Set();
function orderTest() {
let seq = [];
let add = () => set.add(seq.join());
setTimeout(function () {
setTimeout(function () {
seq.push('setTimeout');
if (seq.length === 2) add();
}, 0);
setImmediate(function () {
seq.push('setImmediate');
if (seq.length === 2) add();
});
}, 10);
}
// loop 100 times
for (let i = 0; i < 100; i++) {
orderTest();
}
setTimeout(() => {
// will print one or two items, it's random
for (item of set) {
console.log(item);
}
}, 100);
Объяснения здесь
setTimeout (fn, 0) можно использовать для предотвращения зависания браузера при массовом обновлении. например, в websocket.onmessage у вас могут быть изменения html, и если сообщения продолжают приходить, браузер может зависнуть при использовании setImmidiate
Чтобы понять их глубоко, пожалуйста, однажды пройдите фазы цикла событий.
SetImmediate: выполняется на этапе «проверки». Проверка фаза называется после фазы I / O.
SetTimeOut: выполняется в фазе "таймера". Таймер фаза является первой фазой , но вызывается после I / O фазы, а также Проверка фазы.
Чтобы получить результат детерминированным образом, это будет зависеть от того, на какой фазе находится цикл событий; соответственно, мы можем использовать функцию из двух.
используйте setImmediate (), чтобы не блокировать цикл событий. Обратный вызов будет запущен в следующем цикле событий, как только будет выполнен текущий.
используйте setTimeout () для контролируемых задержек. Функция будет запущена после указанной задержки. Минимальная задержка составляет 1 миллисекунду.