NodeJS - setTimeout (fn, 0) vs setImmediate (fn)


Jawaban:


72

setTimeout sama seperti memanggil fungsi setelah penundaan selesai. Setiap kali sebuah fungsi dipanggil, itu tidak segera dijalankan, tetapi antri sehingga dijalankan setelah semua eventhandler yang sedang dieksekusi dan antri selesai terlebih dahulu. setTimeout (, 0) pada dasarnya berarti mengeksekusi setelah semua fungsi saat ini dalam antrian saat ini dijalankan. Tidak ada jaminan tentang berapa lama waktu yang dibutuhkan.

setImmediate serupa dalam hal ini kecuali bahwa ia tidak menggunakan antrian fungsi. Ia memeriksa antrian eventhandler I / O. Jika semua kejadian I / O dalam snapshot saat ini diproses, callback akan dijalankan. Ini mengantri mereka segera setelah penangan I / O terakhir agak seperti proses.nextTick. Jadi lebih cepat.

Juga (setTimeout, 0) akan lambat karena akan memeriksa pengatur waktu setidaknya sekali sebelum dijalankan. Kadang-kadang bisa dua kali lebih lambat. Ini patokannya.

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})

Keluaran

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)

Yang pertama memberikan ide tentang panggilan tercepat. Anda dapat memeriksa diri Anda sendiri jika setTimeout dipanggil setengah kali dari yang lain. Ingat juga setImmediate akan menyesuaikan dengan panggilan sistem file Anda. Jadi di bawah beban itu akan bekerja lebih sedikit. Saya tidak berpikir setTimeout bisa bekerja lebih baik.

setTimeout adalah cara memanggil fungsi yang tidak mengganggu setelah beberapa waktu. Ini seperti di browser. Ini mungkin tidak cocok untuk sisi server (pikirkan mengapa saya menggunakan benchmark.js bukan setTimeout).


3
Penting untuk diperhatikan bahwa setTimeout tunduk pada penundaan paksa setidaknya empat milidetik jika bertingkat lima kali. lihat spesifikasi html
Jack Allan

Sumber ini (dari jawaban lain) tampaknya membantah beberapa pernyataan di sini: voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout
Dmitri Zaitsev

17

Artikel bagus tentang cara kerja event loop dan menghapus beberapa kesalahpahaman. http://voidcanvas.com/setimmediate-vs-nexttick-vs-settimeout/

Mengutip artikel:

setImmediatecallback dipanggil setelah I / O Queue callbacks selesai atau waktunya habis. setImmediate callbacks ditempatkan di Check Queue, yang diproses setelah I / O Queue.

setTimeout(fn, 0)callback ditempatkan di Timer Queue dan akan dipanggil setelah callback I / O serta callback Check Queue. Sebagai loop peristiwa, proses antrian pengatur waktu terlebih dahulu di setiap iterasi, sehingga mana yang akan dieksekusi terlebih dahulu tergantung pada loop peristiwa fase mana.


antrian setTimeout diproses sebelum panggilan balik I / O. ref: nodejs.org/en/docs/guides/event-loop-timers-and-nexttick
manusia

4

setImmediate () adalah untuk menjadwalkan eksekusi callback segera setelah kejadian I / O callback dan sebelum setTimeout dan setInterval.

setTimeout () adalah untuk menjadwalkan eksekusi callback satu kali setelah penundaan milidetik.

Inilah yang tertulis dalam dokumen.

setTimeout(function() {
  console.log('setTimeout')
}, 0)

setImmediate(function() {
  console.log('setImmediate')
})

Jika Anda menjalankan kode di atas, hasilnya akan seperti ini ... meskipun dokumen saat ini menyatakan bahwa "Untuk menjadwalkan eksekusi callback" langsung "setelah kejadian I / O callback dan sebelum setTimeout dan setInterval." ..

Hasil..

setTimeout

setImmediate

Jika Anda menggabungkan contoh Anda di timer lain, itu selalu mencetak setImmediate diikuti oleh setTimeout.

setTimeout(function() {
  setTimeout(function() {
    console.log('setTimeout')
  }, 0);
  setImmediate(function() {
    console.log('setImmediate')
  });
}, 10);

Jadi kapan Anda akan memilih salah satu dari yang lain?
Shlomi Schwartz

23
Anda tidak menjelaskan mengapa apa yang Anda tunjukkan terjadi. Jawaban ini tidak berguna bagi saya.
Clint Eastwood

3
@Savannah Di hasil pertama Anda, jelaskan mengapa setTimeout dieksekusi terlebih dahulu sebelum setImmediate
Agus Syahputra


1
SetImmediate tidak akan dieksekusi sebelum setTimeout dan setInterval sepanjang waktu
Midhun GS

2

selalu gunakan setImmediate, kecuali jika Anda benar-benar yakin bahwa Anda membutuhkannya setTimeout(,0)(tetapi saya bahkan tidak dapat membayangkan, untuk apa). setImmediatecallback akan hampir selalu dijalankan sebelumnya setTimeout(,0), kecuali saat dipanggil di tik pertama dan di setImmediatecallback.


1
Saya akan mengatakan alasan utama untuk menggunakan setTimeout daripada setImmediate adalah kode Anda perlu dijalankan oleh browser yang tidak menerapkan setImmediate. Meski begitu, Anda bisa membuat shim.
Gregory Magarshak

9
Ini adalah nasihat yang tidak masuk akal. Jika semuanya meminta untuk pergi dulu, karakteristik kinerja yang muncul dari eksekusi asinkron akan menjadi sampah dibandingkan dengan antrian di akhir. setTimeoutharus menjadi tujuan, dengan setImmediatedigunakan hanya jika terbukti perlu.
Rich Remer

1

Benar-benar tidak puas dengan jawaban yang diberikan. Saya memposting apa yang menurut saya merupakan jawaban yang lebih baik di sini: https://stackoverflow.com/a/56724489/5992714

Pertanyaan adalah kemungkinan duplikat dari Mengapa perilaku setTimeout (0) dan setImmediate () tidak ditentukan ketika digunakan dalam modul utama?


1
Harap jangan memposting jawaban yang persis sama untuk dua pertanyaan. Jika pertanyaannya berbeda, sesuaikan jawaban untuk masing-masing pertanyaan. Jika keduanya sama, tandai atau pilih untuk menutup salah satu sebagai duplikat.
Tom Zych

@Tomych mencatat.
manusia

0

Saya rasa jawaban Navya S tidak benar, berikut kode tes saya:

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);

Penjelasannya ada di sini


0

setTimeout (fn, 0) dapat digunakan untuk mencegah browser membeku dalam pembaruan besar-besaran. misalnya di websocket.onmessage, Anda mungkin memiliki perubahan html, dan jika pesan terus datang, browser mungkin berhenti saat menggunakan setImmidiate


0

Untuk memahaminya secara mendalam, harap sekali melalui fase loop peristiwa.

SetImmediate: Ini dijalankan pada fase "check". The cek fase disebut setelah fase I / O.

SetTimeOut: Ini dijalankan dalam fase "timer". The Timer fase adalah tahap pertama tetapi disebut setelah I / O fase serta Periksa fase.

Untuk mendapatkan keluaran secara deterministik, itu akan tergantung pada fase mana loop-peristiwa itu berada; karenanya, kita dapat menggunakan fungsi dari dua fungsi tersebut.


-5

gunakan setImmediate () untuk tidak memblokir event loop. Callback akan berjalan pada loop acara berikutnya, segera setelah yang sekarang selesai.

gunakan setTimeout () untuk penundaan terkontrol. Fungsi akan berjalan setelah penundaan yang ditentukan. Penundaan minimum adalah 1 milidetik.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.