Qual é a diferença entre os dois e quando vou usar um em vez do outro?
Qual é a diferença entre os dois e quando vou usar um em vez do outro?
Respostas:
setTimeout é simplesmente como chamar a função após o término do atraso. Sempre que uma função é chamada, ela não é executada imediatamente, mas enfileirada para que seja executada depois que todos os manipuladores de eventos em execução e atualmente enfileirados terminem primeiro. setTimeout (, 0) significa essencialmente executar depois que todas as funções atuais na fila atual forem executadas. Nenhuma garantia pode ser feita sobre quanto tempo isso pode levar.
setImmediate é semelhante nesse aspecto, exceto que não usa fila de funções. Ele verifica a fila de manipuladores de eventos de E / S. Se todos os eventos de E / S no instantâneo atual forem processados, ele executa o retorno de chamada. Ele os enfileira imediatamente após o último manipulador de E / S, de forma semelhante a process.nextTick. Portanto, é mais rápido.
Além disso, (setTimeout, 0) será lento porque verificará o cronômetro pelo menos uma vez antes de executar. Às vezes, pode ser duas vezes mais lento. Aqui está uma referência.
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})
Resultado
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)
Primeiro dá-se uma ideia das chamadas mais rápidas possíveis. Você pode verificar se setTimeout é chamado a metade das vezes que outro. Lembre-se também de que o setImmediate se ajustará às chamadas do seu sistema de arquivos. Portanto, sob carga, o desempenho será menor. Não acho que setTimeout possa fazer melhor.
setTimeout é uma forma não intrusiva de chamar funções depois de algum tempo. É exatamente como no navegador. Pode não ser adequado para o lado do servidor (pense por que usei benchmark.js e não setTimeout).
Um ótimo artigo sobre como funciona o loop de eventos e elimina alguns equívocos. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Citando o artigo:
setImmediate
os retornos de chamada são chamados depois que os retornos de chamada da Fila de E / S são concluídos ou expiram. Os retornos de chamada setImmediate são colocados em Check Queue, que são processados após I / O Queue.
setTimeout(fn, 0)
callbacks são colocados em Timer Queue e serão chamados após callbacks de I / O, bem como callbacks Check Queue. Como loop de evento, processe a fila do cronômetro primeiro em cada iteração, de forma que qual delas será executada primeiro depende de qual loop de evento de fase é.
setImmediate () é para agendar a execução imediata de callback após callbacks de eventos de E / S e antes de setTimeout e setInterval.
setTimeout () é para agendar a execução de um retorno de chamada único após um atraso de milissegundos.
Isso é o que dizem os documentos.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
Se você executar o código acima, o resultado será assim ... embora o documento atual indique que "Para agendar a execução" imediata "do retorno de chamada após os retornos de chamada de eventos de E / S e antes de setTimeout e setInterval." ..
Resultado..
setTimeout
setImmediate
Se você envolver seu exemplo em outro cronômetro, ele sempre imprimirá setImmediate seguido por setTimeout.
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
use sempre setImmediate
, a menos que você tenha certeza de que precisa setTimeout(,0)
(mas nem consigo imaginar para quê). setImmediate
o callback quase sempre será executado antes setTimeout(,0)
, exceto quando chamado no primeiro tick e no setImmediate
callback.
setTimeout
deve ser o ponto de partida, sendo setImmediate
usado somente quando for necessário.
Totalmente insatisfeito com as respostas fornecidas. Publiquei o que considero uma resposta melhor aqui: https://stackoverflow.com/a/56724489/5992714
Perguntas é uma possível duplicata de Por que o comportamento de setTimeout (0) e setImmediate () é indefinido quando usado no módulo principal?
Acho que a resposta do Navya S não está correta, aqui está o meu código de teste:
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);
As explicações estão aqui
setTimeout (fn, 0) pode ser usado para evitar que o navegador congele em uma atualização massiva. por exemplo, em websocket.onmessage, você pode ter alterações de html e, se as mensagens continuarem chegando, o navegador pode congelar ao usar setImmidiate
Para entendê-los profundamente, passe uma vez pelas fases do loop de eventos.
SetImmediate: é executado na fase de "verificação". A fase de verificação é chamada após a fase de E / S.
SetTimeOut: É executado na fase de "cronômetro". A fase do temporizador é a primeira fase, mas é chamada após a fase de E / S , bem como a fase de verificação .
Para obter a saída de maneira determinística, dependerá de qual fase está o loop de eventos; consequentemente, podemos usar a função de dois.
use setImmediate () para não bloquear o loop de eventos. O retorno de chamada será executado no próximo loop de evento, assim que o atual for concluído.
use setTimeout () para atrasos controlados. A função será executada após o atraso especificado. O atraso mínimo é de 1 milissegundo.