Яка різниця між цими двома, і коли я буду використовувати один над іншим?
Яка різниця між цими двома, і коли я буду використовувати один над іншим?
Відповіді:
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 вдвічі частіше, ніж інші. Також пам’ятайте, що setImmediate налаштується на виклики вашої файлової системи. Отже, під навантаженням він буде працювати менше. Я не думаю, що setTimeout може зробити краще.
setTimeout - це ненав’язливий спосіб виклику функцій через деякий час. Це так само, як у браузері. Можливо, він не підходить для сторони сервера (подумайте, чому я використав benchmark.js не setTimeout).
Чудова стаття про те, як працює цикл подій, і виправляє деякі помилки. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Посилаючись на статтю:
setImmediateзворотні дзвінки викликаються після того, як зворотні виклики вводу-виводу закінчені або закінчився час очікування. setImmediate зворотні виклики розміщуються в Check Queue, які обробляються після I / O Queue.
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використанням лише тоді, коли це показано необхідним.
Повністю незадоволений наданими відповідями. Я розмістив тут, на мою думку, кращі відповіді: https://stackoverflow.com/a/56724489/5992714
Запитання - це можливий дублікат Чому поведінка 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 мілісекунда.