Jaka jest różnica między tymi dwoma i kiedy użyję jednego nad drugim?
Jaka jest różnica między tymi dwoma i kiedy użyję jednego nad drugim?
Odpowiedzi:
setTimeout jest po prostu jak wywołanie funkcji po zakończeniu opóźnienia. Za każdym razem, gdy wywoływana jest funkcja, nie jest ona wykonywana natychmiast, ale umieszczana w kolejce, tak aby była wykonywana po zakończeniu wszystkich wykonujących i aktualnie umieszczonych w kolejce programów obsługi zdarzeń. setTimeout (, 0) zasadniczo oznacza wykonanie po wykonaniu wszystkich bieżących funkcji w obecnej kolejce. Nie można zagwarantować, jak długo to potrwa.
setImmediate jest pod tym względem podobna, z tą różnicą, że nie używa kolejki funkcji. Sprawdza kolejkę obsługi zdarzeń I / O. Jeśli wszystkie zdarzenia we / wy w bieżącej migawce są przetwarzane, wykonuje wywołanie zwrotne. Kolejkuje je natychmiast po ostatnim programie obsługi we / wy, podobnie jak process.nextTick. Więc to jest szybsze.
Również (setTimeout, 0) będzie wolne, ponieważ przynajmniej raz sprawdzi licznik czasu przed wykonaniem. Czasami może być dwa razy wolniejsze. Oto punkt odniesienia.
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})
Wynik
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)
Pierwsza daje wyobrażenie o możliwie najszybszych połączeniach. Możesz sam sprawdzić, czy setTimeout jest wywoływany o połowę mniej niż inne. Pamiętaj również, że setImmediate dostosuje się do wywołań twojego systemu plików. Więc pod obciążeniem będzie działać mniej. Nie sądzę, żeby setTimeout działał lepiej.
setTimeout to nieinwazyjny sposób wywoływania funkcji po pewnym czasie. Podobnie jak w przeglądarce. Może nie być odpowiedni dla serwera (pomyśl, dlaczego użyłem benchmark.js, a nie setTimeout).
Świetny artykuł o tym, jak działa pętla zdarzeń i wyjaśnia niektóre nieporozumienia. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Cytując artykuł:
setImmediatewywołania zwrotne są wywoływane po zakończeniu lub przekroczeniu limitu czasu wywołań zwrotnych kolejki we / wy. setImmediate wywołania zwrotne są umieszczane w kolejce sprawdzania, które są przetwarzane po kolejce we / wy.
setTimeout(fn, 0)callbacki są umieszczane w Timer Queue i będą wywoływane po wywołaniach I / O oraz Check Queue. Jako pętla zdarzeń przetwórz kolejkę timera jako pierwszą w każdej iteracji, więc to, która z nich zostanie wykonana jako pierwsza, zależy od tego, która pętla zdarzeń fazy jest.
setImmediate () służy do planowania natychmiastowego wykonania wywołania zwrotnego po wywołaniach zwrotnych zdarzeń I / O, a przed ustawieniami setTimeout i setInterval.
setTimeout () służy do zaplanowania wykonania jednorazowego wywołania zwrotnego po upływie milisekund opóźnienia.
Tak mówią dokumenty.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
Jeśli uruchomisz powyższy kod, wynik będzie taki ... mimo że w bieżącym dokumencie jest napisane, że „Aby zaplanować„ natychmiastowe ”wykonanie wywołania zwrotnego po wywołaniach zwrotnych zdarzeń we / wy, a przed ustawieniami setTimeout i setInterval.” ..
Wynik..
setTimeout
setImmediate
Jeśli umieścisz swój przykład w innym zegarze, zawsze wypisuje setImmediate, po którym następuje setTimeout.
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
zawsze używaj setImmediate, chyba że jesteś naprawdę pewien, że potrzebujesz setTimeout(,0)(ale nie mogę sobie nawet wyobrazić, po co). setImmediatecallback prawie zawsze będzie wykonywany wcześniej setTimeout(,0), z wyjątkiem wywołania w pierwszym tiku i podczas setImmediatecallback.
setTimeoutpowinny być setImmediateużywane tylko wtedy, gdy okaże się to konieczne.
Całkowicie niezadowolony z udzielonych odpowiedzi. To, co uważam za lepsze odpowiedzi, zamieściłem tutaj: https://stackoverflow.com/a/56724489/5992714
Pytania są możliwym duplikatem Dlaczego zachowanie setTimeout (0) i setImmediate () jest niezdefiniowane, gdy są używane w module głównym?
Myślę, że odpowiedź Navya S nie jest poprawna, oto mój kod testowy:
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);
Wyjaśnienia są tutaj
setTimeout (fn, 0) może służyć do zapobiegania zawieszaniu się przeglądarki podczas masowej aktualizacji. na przykład w websocket.onmessage, możesz mieć zmiany w html, a jeśli wiadomości będą przychodzić, przeglądarka może się zawiesić podczas używania setImmidiate
Aby je dogłębnie zrozumieć, proszę przejść przez fazy pętli zdarzeń.
SetImmediate: jest wykonywany w fazie „sprawdzania”. Faza sprawdzania jest wywoływana po fazie I / O.
SetTimeOut: Jest wykonywany w fazie „timera”. Faza timera jest pierwszą fazą, ale jest wywoływana po fazie I / O oraz fazie Check .
Aby uzyskać wynik w sposób deterministyczny, będzie to zależeć od fazy pętli zdarzeń; odpowiednio, możemy użyć funkcji z dwóch.
użyj setImmediate (), aby nie blokować pętli zdarzeń. Wywołanie zwrotne zostanie uruchomione w następnej pętli zdarzeń, gdy tylko bieżąca zostanie wykonana.
użyj setTimeout () dla kontrolowanych opóźnień. Funkcja uruchomi się po określonym czasie. Minimalne opóźnienie to 1 milisekunda.