Bu ikisi arasındaki fark nedir ve birini diğerine göre ne zaman kullanacağım?
Bu ikisi arasındaki fark nedir ve birini diğerine göre ne zaman kullanacağım?
Yanıtlar:
setTimeout , gecikme bittikten sonra işlevi çağırmak gibidir. Bir işlev çağrıldığında, hemen çalıştırılmaz, ancak sıraya alınır, böylece tüm çalıştırma işlemlerinden sonra yürütülür ve şu anda sıraya alınmış olan çiftler birinci bitirir. setTimeout (, 0) esasen mevcut kuyruktaki tüm geçerli işlevler yürütüldükten sonra çalıştırılması anlamına gelir. Ne kadar süreceği konusunda hiçbir garanti verilemez.
setImmediate , işlev kuyruğunu kullanmaması dışında bu açıdan benzerdir. G / Ç çift taşıyıcılarının sırasını kontrol eder. Geçerli anlık görüntüdeki tüm G / Ç olayları işlenirse, geri aramayı yürütür. İşlem.nextTick gibi, son G / Ç işleyicisinden hemen sonra onları sıraya koyar. Yani daha hızlı.
Ayrıca (setTimeout, 0) yavaş olacaktır çünkü yürütmeden önce zamanlayıcıyı en az bir kez kontrol edecektir. Bazen iki kat daha yavaş olabilir. İşte bir kriter.
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})
Çıktı
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)
İlki, mümkün olan en hızlı aramalar hakkında fikir verir. SetTimeout'un diğerlerinin yarısı kadar çağrılıp çağrılmadığını kendiniz kontrol edebilirsiniz. Ayrıca setImmediate'in dosya sistemi çağrılarınıza uyum sağlayacağını unutmayın. Yani yük altında daha az performans gösterecektir. SetTimeout'un daha iyisini yapabileceğini sanmıyorum.
setTimeout, bir süre sonra işlevleri çağırmanın müdahaleci olmayan bir yoludur. Tıpkı tarayıcıdaki gibi. Sunucu tarafı için uygun olmayabilir (neden setTimeout değil benchmark.js kullandığımı düşünün).
Olay döngüsünün nasıl çalıştığı ve bazı yanlış anlamaları ortadan kaldırdığı hakkında harika bir makale. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/
Makaleden alıntı yapmak:
setImmediategeri aramalar, G / Ç Sırası geri aramaları tamamlandıktan veya zaman aşımına uğradıktan sonra çağrılır. setImmediate geri aramaları, G / Ç Sırasından sonra işlenen Kontrol Sırasına yerleştirilir.
setTimeout(fn, 0)geri aramalar Zamanlayıcı Kuyruğuna yerleştirilir ve G / Ç geri aramalarının yanı sıra Check Queue geri aramalarından sonra çağrılır. Olay döngüsü olarak, her yinelemede ilk olarak zamanlayıcı kuyruğunu işleyin, böylece hangisinin ilk olarak yürütüleceği, hangi faz olay döngüsünün olduğuna bağlıdır.
setImmediate () , G / Ç olayları geri aramalarından sonra ve setTimeout ve setInterval'dan önce geri aramanın hemen yürütülmesini planlamaktır.
setTimeout () , milisaniye gecikmesinden sonra bir kerelik geri aramanın yürütülmesini planlamaktır.
Belgelerin söylediği bu.
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
Yukarıdaki kodu çalıştırırsanız, sonuç şu şekilde olacaktır ... mevcut belgede "G / Ç olayları geri aramalarından sonra ve setTimeout ve setInterval'dan önce geri aramanın" anında "yürütülmesini planlamak için." ..
Sonuç..
setTimeout
setImmediate
Örneğinizi başka bir zamanlayıcıya sararsanız, her zaman setImmediate ve ardından setTimeout yazdırır.
setTimeout(function() {
setTimeout(function() {
console.log('setTimeout')
}, 0);
setImmediate(function() {
console.log('setImmediate')
});
}, 10);
setImmediateİhtiyaç duyduğunuzdan gerçekten emin değilseniz her zaman kullanın setTimeout(,0)(ama ne için olduğunu hayal bile edemiyorum). setImmediategeri arama, setTimeout(,0)ilk tikte ve setImmediategeri aramada çağrılmadıkça hemen hemen her zaman daha önce yürütülür .
setTimeoutile, go-olmalıdır setImmediategerekli olduğu gösterilmiştir yalnızca kullandı.
Verilen cevaplardan tamamen memnun kalmadım. Burada daha iyi bir cevap olduğunu düşündüğüm şeyi yayınladım: https://stackoverflow.com/a/56724489/5992714
Sorular, ana modülde kullanıldığında setTimeout (0) ve setImmediate () davranışları neden tanımsızdır?
Navya S'nin cevabının doğru olmadığını düşünüyorum , işte test kodum:
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);
Açıklamalar burada
setTimeout (fn, 0), tarayıcının büyük güncellemelerde donmasını önlemek için kullanılabilir. örneğin websocket.onmessage'da html değişiklikleriniz olabilir ve mesajlar gelmeye devam ederse setImmidiate kullanırken tarayıcı donabilir
Bunları derinlemesine anlamak için lütfen bir kez olay döngüsü aşamalarından geçin.
SetImmediate: "kontrol" aşamasında çalıştırılır. Onay faz I / O aşamasından sonra adlandırılır.
SetTimeOut: "timer" aşamasında çalıştırılır. Zamanlayıcı faz ilk aşamasıdır ama sonra çağrılan G / Ç fazı yanı sıra kontrol fazı.
Çıktıyı belirleyici bir şekilde elde etmek için, olay döngüsünün hangi fazda olduğuna bağlı olacaktır; buna göre, işlevi ikiden kullanabiliriz.