อะไรคือความแตกต่างระหว่างสองสิ่งนี้และฉันจะใช้อีกอันหนึ่งเมื่อใด
อะไรคือความแตกต่างระหว่างสองสิ่งนี้และฉันจะใช้อีกอันหนึ่งเมื่อใด
คำตอบ:
setTimeoutก็เหมือนกับการเรียกใช้ฟังก์ชันหลังจากการหน่วงเวลาเสร็จสิ้น เมื่อใดก็ตามที่มีการเรียกใช้ฟังก์ชันจะไม่ถูกเรียกใช้งานทันที แต่อยู่ในคิวเพื่อให้ดำเนินการหลังจากที่ตัวจัดการเหตุการณ์ที่ดำเนินการและที่จัดคิวในปัจจุบันเสร็จสิ้นก่อน setTimeout (, 0) โดยพื้นฐานแล้วหมายถึงการดำเนินการหลังจากที่ฟังก์ชันปัจจุบันทั้งหมดในคิวปัจจุบันได้รับการดำเนินการ ไม่สามารถรับประกันได้ว่าจะใช้เวลานานเท่าใด
setImmediateมีความคล้ายคลึงกันในเรื่องนี้ยกเว้นว่าจะไม่ใช้คิวของฟังก์ชัน ตรวจสอบคิวของตัวจัดการเหตุการณ์ I / O หากเหตุการณ์ I / O ทั้งหมดในสแน็ปช็อตปัจจุบันถูกประมวลผลเหตุการณ์นั้นจะเรียกใช้การเรียกกลับ มันเข้าคิวทันทีหลังจากตัวจัดการ I / O ตัวสุดท้ายที่ค่อนข้างคล้ายกับ 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การโทรกลับจะถูกเรียกหลังจากการโทรกลับของคิว I / O เสร็จสิ้นหรือหมดเวลา การเรียกกลับ setImmediate จะอยู่ใน Check Queue ซึ่งประมวลผลหลังจาก I / O Queue
setTimeout(fn, 0)การโทรกลับจะอยู่ใน Timer Queue และจะถูกเรียกหลังจากการโทรกลับของ I / O เช่นเดียวกับการเรียกกลับของ Check Queue ในฐานะลูปเหตุการณ์ให้ประมวลผลคิวตัวจับเวลาก่อนในการวนซ้ำแต่ละครั้งดังนั้นคิวใดจะถูกดำเนินการก่อนจึงขึ้นอยู่กับว่าลูปเหตุการณ์เฟสใด
setImmediate ()คือกำหนดเวลาดำเนินการเรียกกลับทันทีหลังจากการเรียกกลับเหตุการณ์ I / O และก่อน setTimeout และ setInterval
setTimeout ()คือการกำหนดเวลาการดำเนินการโทรกลับครั้งเดียวหลังจากล่าช้าในมิลลิวินาที
นี่คือสิ่งที่เอกสารกล่าว
setTimeout(function() {
console.log('setTimeout')
}, 0)
setImmediate(function() {
console.log('setImmediate')
})
หากคุณเรียกใช้โค้ดด้านบนผลลัพธ์จะเป็นเช่นนี้ ... แม้ว่าเอกสารปัจจุบันจะระบุว่า "เพื่อกำหนดเวลาการเรียกกลับ" ทันที "หลังจากการเรียกกลับเหตุการณ์ I / O และก่อน 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 มิลลิวินาที