Saya baru-baru ini mengalami bug yang agak jahat, di mana kode itu memuat secara <select>
dinamis melalui JavaScript. Ini dimuat secara dinamis <select>
memiliki nilai yang dipilih sebelumnya. Di IE6, kami sudah memiliki kode untuk memperbaiki yang dipilih <option>
, karena kadang-kadang <select>
's selectedIndex
nilai akan keluar dari sinkron dengan yang dipilih <option>
' s index
atribut, seperti di bawah ini:
field.selectedIndex = element.index;
Namun, kode ini tidak berfungsi. Meskipun bidang selectedIndex
itu disetel dengan benar, indeks yang salah akan dipilih. Namun, jika saya memasukkan alert()
pernyataan pada saat yang tepat, opsi yang benar akan dipilih. Berpikir ini mungkin semacam masalah waktu, saya mencoba sesuatu yang acak yang saya lihat dalam kode sebelumnya:
var wrapFn = (function() {
var myField = field;
var myElement = element;
return function() {
myField.selectedIndex = myElement.index;
}
})();
setTimeout(wrapFn, 0);
Dan ini berhasil!
Saya punya solusi untuk masalah saya, tetapi saya tidak nyaman karena saya tidak tahu persis mengapa ini memperbaiki masalah saya. Adakah yang punya penjelasan resmi? Masalah browser apa yang saya hindari dengan memanggil fungsi saya "nanti" menggunakan setTimeout()
?
sumber
setTimeout(fn)
sama dengansetTimeout(fn, 0)
, btw.Jawaban:
Dalam pertanyaan tersebut, ada kondisi ras antara:
Kode Anda secara konsisten memenangkan perlombaan ini dan mencoba untuk mengatur pilihan drop-down sebelum browser siap, yang berarti bahwa bug akan muncul.
Ras ini ada karena JavaScript memiliki utas eksekusi tunggal yang dibagikan dengan rendering halaman. Akibatnya, menjalankan JavaScript memblokir pembaruan DOM.
Solusi Anda adalah:
Memanggil
setTimeout
dengan callback, dan nol sebagai argumen kedua akan menjadwalkan panggilan balik untuk dijalankan secara tidak sinkron , setelah penundaan sesingkat mungkin - yang akan menjadi sekitar 10 ms ketika tab memiliki fokus dan utas eksekusi JavaScript tidak sibuk.Solusi OP, oleh karena itu untuk menunda sekitar 10 ms, pengaturan indeks yang dipilih. Ini memberi browser kesempatan untuk menginisialisasi DOM, memperbaiki bug.
Setiap versi Internet Explorer menunjukkan perilaku yang aneh dan penyelesaian semacam ini kadang-kadang diperlukan. Atau mungkin itu adalah bug asli dalam basis kode OP.
Lihat Philip Roberts bicara "Apa-apaan acara itu?" untuk penjelasan yang lebih menyeluruh.
sumber
Kata pengantar:
Beberapa jawaban lain benar tetapi tidak benar-benar menggambarkan apa masalah yang sedang dipecahkan, jadi saya membuat jawaban ini untuk menyajikan ilustrasi terperinci itu.
Karena itu, saya memposting perincian terperinci tentang apa yang dilakukan browser dan bagaimana menggunakan
setTimeout()
bantuan . Itu terlihat gondrong tetapi sebenarnya sangat sederhana dan mudah - saya hanya membuatnya sangat rinci.UPDATE: Saya telah membuat JSFiddle untuk live-mendemonstrasikan penjelasan di bawah ini: http://jsfiddle.net/C2YBE/31/ . Banyak terima kasih kepada @ThangChung untuk membantu memulainya.
UPDATE2: Kalau-kalau situs web JSFiddle mati, atau menghapus kode, saya menambahkan kode ke jawaban ini di akhir.
RINCIAN :
Bayangkan aplikasi web dengan tombol "lakukan sesuatu" dan hasil div.
The
onClick
handler untuk tombol "melakukan sesuatu" panggilan fungsi "LongCalc ()", yang melakukan 2 hal:Menghitung sangat lama
Mencetak hasil perhitungan ke dalam div hasil.
Sekarang, pengguna Anda mulai menguji ini, klik tombol "lakukan sesuatu", dan halaman yang tampaknya tidak melakukan apa-apa selama 3 menit, mereka gelisah, klik lagi tombol, tunggu 1 menit, tidak ada yang terjadi, klik tombol lagi ...
Masalahnya jelas - Anda menginginkan DIV "Status", yang menunjukkan apa yang terjadi. Mari kita lihat cara kerjanya.
Jadi Anda menambahkan "Status" DIV (awalnya kosong), dan memodifikasi
onclick
handler (fungsiLongCalc()
) untuk melakukan 4 hal:Isi status "Menghitung ... mungkin memerlukan waktu ~ 3 menit" ke status DIV
Menghitung sangat lama
Mencetak hasil perhitungan ke dalam div hasil.
Mengisi status "Perhitungan selesai" ke dalam status DIV
Dan, Anda dengan senang hati memberikan aplikasi kepada pengguna untuk diuji ulang.
Mereka kembali padamu tampak sangat marah. Dan jelaskan bahwa ketika mereka mengklik tombol, Status DIV tidak pernah diperbarui dengan status "Menghitung ..." !!!
Anda menggaruk-garuk kepala, bertanya-tanya di StackOverflow (atau membaca dokumen atau google), dan menyadari masalahnya:
Browser menempatkan semua tugas "TODO" (baik tugas UI dan perintah JavaScript) yang dihasilkan dari peristiwa ke dalam satu antrian . Dan sayangnya, menggambar ulang DIV "Status" dengan nilai "Menghitung ..." yang baru adalah TODO terpisah yang menuju akhir antrian!
Berikut ini rincian peristiwa selama pengujian pengguna Anda, konten antrian setelah setiap peristiwa:
[Empty]
[Execute OnClick handler(lines 1-4)]
[Execute OnClick handler(lines 2-4), re-draw Status DIV with new "Calculating" value]
. Harap perhatikan bahwa meskipun perubahan DOM terjadi secara instan, untuk menggambar ulang elemen DOM yang sesuai, Anda memerlukan acara baru, yang dipicu oleh perubahan DOM, yang berlangsung di akhir antrian .[Execute OnClick handler(lines 3-4), re-draw Status DIV with "Calculating" value]
.[Execute OnClick handler(line 4), re-draw Status DIV with "Calculating" value, re-draw result DIV with result]
.[Execute OnClick handler, re-draw Status DIV with "Calculating" value, re-draw result DIV with result; re-draw Status DIV with "DONE" value]
.return
darionclick
sub handler. Kami mengambil "Execute OnClick handler" dari antrian dan mulai menjalankan item berikutnya pada antrian.Jadi, masalah yang mendasarinya adalah bahwa acara undian ulang untuk "Status" DIV ditempatkan pada antrian di akhir, SETELAH acara "eksekusi garis 2" yang membutuhkan waktu 3 menit, sehingga pengundian ulang yang sebenarnya tidak terjadi sampai SETELAH perhitungan dilakukan.
Untuk penyelamatan datang
setTimeout()
. Bagaimana ini membantu? Karena dengan memanggil kode lama-eksekusi viasetTimeout
, Anda benar-benar membuat 2 peristiwa:setTimeout
eksekusi itu sendiri, dan (karena 0 batas waktu), entri entri antrian terpisah untuk kode yang dieksekusi.Jadi, untuk memperbaiki masalah Anda, Anda memodifikasi
onClick
handler Anda menjadi DUA pernyataan (dalam fungsi baru atau hanya satu blok di dalamnyaonClick
):Isi status "Menghitung ... mungkin memerlukan waktu ~ 3 menit" ke status DIV
Jalankan
setTimeout()
dengan 0 batas waktu dan panggilan untukLongCalc()
berfungsi .LongCalc()
fungsi hampir sama seperti terakhir kali tetapi jelas tidak memiliki status "Menghitung ..." pembaruan DIV sebagai langkah pertama; dan bukannya memulai perhitungan segera.Jadi, seperti apa urutan kejadian dan antriannya sekarang?
[Empty]
[Execute OnClick handler(status update, setTimeout() call)]
[Execute OnClick handler(which is a setTimeout call), re-draw Status DIV with new "Calculating" value]
.[re-draw Status DIV with "Calculating" value]
. Antrian tidak memiliki yang baru di dalamnya selama 0 detik lagi.[re-draw Status DIV with "Calculating" value, execute LongCalc (lines 1-3)]
.[execute LongCalc (lines 1-3)]
. Harap dicatat bahwa acara menggambar ulang ini mungkin benar-benar terjadi SEBELUM alarm berbunyi, yang juga berfungsi.Hore! Status DIV baru saja diperbarui ke "Menghitung ..." sebelum perhitungan dimulai !!!
Di bawah ini adalah contoh kode dari JSFiddle yang menggambarkan contoh-contoh ini: http://jsfiddle.net/C2YBE/31/ :
Kode HTML:
Kode JavaScript: (Dieksekusi pada
onDomReady
dan mungkin memerlukan jQuery 1.9)sumber
Lihatlah artikel John Resig tentang Cara Kerja Pengatur Waktu JavaScript . Ketika Anda mengatur batas waktu, itu sebenarnya mengantri kode asinkron sampai mesin mengeksekusi tumpukan panggilan saat ini.
sumber
setTimeout()
memberi Anda waktu hingga elemen DOM dimuat, meskipun diatur ke 0.Lihat ini: setTimeout
sumber
Sebagian besar browser memiliki proses yang disebut utas utama, yang bertanggung jawab untuk menjalankan beberapa tugas JavaScript, pembaruan UI, misalnya: melukis, menggambar ulang atau merefow, dll.
Beberapa eksekusi JavaScript dan tugas pembaruan UI diantrekan ke antrian pesan browser, kemudian dikirim ke utas utama browser untuk dieksekusi.
Ketika pembaruan UI dihasilkan saat utas utama sedang sibuk, tugas ditambahkan ke dalam antrian pesan.
setTimeout(fn, 0);
tambahkan inifn
ke akhir antrian yang akan dieksekusi. Ini menjadwalkan tugas yang akan ditambahkan pada antrian pesan setelah jumlah waktu tertentu.sumber
add this fn to the end of the queue
. Yang terpenting adalah di mana tepatnyasetTimeout
menambahkan fungsi ini, akhir dari siklus loop ini atau sangat awal siklus loop berikutnya.Ada jawaban terbalik yang bertentangan di sini, dan tanpa bukti tidak ada cara untuk mengetahui siapa yang harus dipercaya. Inilah bukti bahwa @DVK benar dan @SalvadorDali salah. Klaim terakhir:
Batas waktu minimum 4 ms tidak relevan dengan apa yang terjadi. Apa yang sebenarnya terjadi adalah setTimeout mendorong fungsi callback ke akhir antrian eksekusi. Jika setelah setTimeout (panggilan balik, 0) Anda memiliki kode pemblokiran yang membutuhkan beberapa detik untuk dijalankan, panggilan balik tidak akan dieksekusi selama beberapa detik, sampai kode pemblokiran selesai. Coba kode ini:
Output adalah:
sumber
Salah satu alasan untuk melakukan itu adalah untuk menunda eksekusi kode ke loop acara berikutnya yang terpisah. Ketika menanggapi acara browser dari beberapa jenis (klik mouse, misalnya), kadang-kadang perlu untuk melakukan operasi hanya setelah acara saat ini diproses. The
setTimeout()
fasilitas adalah cara paling sederhana untuk melakukannya.sunting sekarang karena tahun 2015 saya harus mencatat bahwa ada juga
requestAnimationFrame()
, yang tidak persis sama tetapi cukup dekatsetTimeout(fn, 0)
sehingga layak disebut.sumber
Ini adalah pertanyaan lama dengan jawaban lama. Saya ingin menambahkan tampilan baru pada masalah ini dan untuk menjawab mengapa ini terjadi dan bukan mengapa ini berguna.
Jadi, Anda memiliki dua fungsi:
dan kemudian memanggil mereka dalam urutan berikut
f1(); f2();
hanya untuk melihat bahwa yang kedua dieksekusi terlebih dahulu.Dan inilah alasannya: tidak mungkin untuk memiliki
setTimeout
waktu tunda 0 milidetik. Nilai minimum ditentukan oleh browser dan bukan 0 milidetik. Secara historis browser menetapkan ini minimum hingga 10 milidetik, tetapi spesifikasi HTML5 dan browser modern ditetapkan pada 4 milidetik.Juga dari mozilla:
Informasi PS diambil setelah membaca artikel berikut .
sumber
setTimeout(fn,0)
bermanfaat.setTimeout
/setInterval
lebih dari lima level; jika belum, minimum adalah 0 ms (apa dengan mesin waktu kurang). Dokumen Mozilla memperluas bahwa untuk mencakup kasus yang berulang, bukan hanya bersarang (jadisetInterval
dengan interval 0 akan menjadwal ulang segera beberapa kali, kemudian menunda lebih lama setelah itu), tetapi penggunaan sederhanasetTimeout
dengan sarang minimal diizinkan untuk segera mengantre.Karena sedang melewati durasi
0
, saya kira itu untuk menghapus kode yang diteruskan kesetTimeout
dari aliran eksekusi. Jadi jika itu adalah fungsi yang bisa memakan waktu cukup lama, itu tidak akan mencegah eksekusi kode selanjutnya.sumber
Kedua jawaban teratas ini salah. Lihatlah deskripsi MDN pada model concurrency dan loop acara , dan akan menjadi jelas apa yang terjadi (sumber daya MDN adalah permata nyata). Dan hanya menggunakan
setTimeout
dapat menambahkan masalah yang tidak terduga dalam kode Anda selain "menyelesaikan" masalah kecil ini.Apa sebenarnya terjadi di sini bukanlah bahwa "browser mungkin belum siap karena konkurensi," atau sesuatu yang berdasarkan pada "setiap baris adalah peristiwa yang ditambahkan ke bagian belakang antrian".
The jsfiddle disediakan oleh DVK memang menggambarkan masalah, tapi penjelasannya untuk itu tidak benar.
Apa yang terjadi dalam kodenya adalah bahwa dia pertama kali memasang pengendali acara ke
click
acara tersebut di#do
tombol.Kemudian, ketika Anda benar-benar mengklik tombol, a
message
dibuat merujuk fungsi event handler, yang akan ditambahkan kemessage queue
. Ketikaevent loop
mencapai pesan ini, itu menciptakan aframe
on the stack, dengan pemanggilan fungsi ke pengendali event klik di jsfiddle.Dan di sinilah mulai menarik. Kami sudah terbiasa menganggap Javascript sebagai tidak sinkron sehingga kami cenderung mengabaikan fakta kecil ini: Setiap frame harus dieksekusi, secara penuh, sebelum frame berikutnya dapat dieksekusi . Tidak ada konkurensi, teman.
Apa artinya ini? Ini berarti bahwa setiap kali suatu fungsi dipanggil dari antrian pesan, ia memblokir antrian sampai tumpukan yang dihasilkannya dikosongkan. Atau, dalam istilah yang lebih umum, itu memblokir sampai fungsi telah kembali. Dan itu memblokir segalanya , termasuk operasi rendering DOM, scrolling, dan yang lainnya. Jika Anda ingin konfirmasi, coba saja tambahkan durasi operasi yang berjalan lama di biola (mis. Jalankan loop luar 10 kali lebih banyak), dan Anda akan melihat bahwa ketika sedang berjalan, Anda tidak dapat menggulir halaman. Jika berjalan cukup lama, browser Anda akan menanyakan apakah Anda ingin mematikan prosesnya, karena itu membuat halaman menjadi tidak responsif. Frame sedang dieksekusi, dan loop acara dan antrian pesan macet sampai selesai.
Jadi mengapa efek samping teks ini tidak diperbarui? Karena ketika Anda telah mengubah nilai elemen dalam DOM - Anda dapat
console.log()
nilainya segera setelah mengubahnya dan melihat bahwa itu telah diubah (yang menunjukkan mengapa penjelasan DVK tidak benar) - browser sedang menunggu tumpukan untuk menguras (ituon
fungsi penangan untuk kembali) dan dengan demikian pesan untuk selesai, sehingga pada akhirnya bisa menyelesaikan mengeksekusi pesan yang telah ditambahkan oleh runtime sebagai reaksi terhadap operasi mutasi kami, dan untuk mencerminkan mutasi itu di UI .Ini karena kami sebenarnya menunggu kode selesai berjalan. Kami belum mengatakan "seseorang mengambil ini dan kemudian memanggil fungsi ini dengan hasilnya, terima kasih, dan sekarang saya sudah selesai imma kembali, lakukan apa pun sekarang," seperti yang biasa kita lakukan dengan Javascript asinkron berbasis acara kami. Kami memasukkan fungsi event handler klik, kami memperbarui elemen DOM, kami memanggil fungsi lain, fungsi lainnya bekerja untuk waktu yang lama dan kemudian kembali, kami kemudian memperbarui elemen DOM yang sama, dan kemudian kami kembali dari fungsi awal, secara efektif mengosongkan tumpukan. Dan kemudian browser dapat membuka pesan berikutnya dalam antrian, yang mungkin merupakan pesan yang dihasilkan oleh kami dengan memicu beberapa jenis acara "on-DOM-mutation" internal.
UI browser tidak dapat (atau memilih untuk tidak) memperbarui UI sampai frame yang sedang dieksekusi selesai (fungsi telah kembali). Secara pribadi, saya pikir ini bukan dengan desain daripada pembatasan.
Mengapa
setTimeout
hal itu berhasil? Ia melakukannya, karena ia secara efektif menghilangkan panggilan ke fungsi yang sudah berjalan lama dari kerangkanya sendiri, menjadwalkannya untuk dieksekusi nanti dalamwindow
konteksnya, sehingga ia sendiri dapat segera kembali dan memungkinkan antrian pesan untuk memproses pesan lainnya. Dan idenya adalah bahwa pesan "saat pembaruan" UI yang telah dipicu oleh kami di Javascript saat mengubah teks di DOM sekarang berada di depan pesan yang antri untuk fungsi jangka panjang, sehingga pembaruan UI terjadi sebelum kami memblokir untuk waktu yang lama.Perhatikan bahwa a) Fungsi yang berjalan lama masih memblokir semua saat dijalankan, dan b) Anda tidak dijamin bahwa pembaruan UI sebenarnya ada di depannya dalam antrian pesan. Pada browser Chrome Juni 2018 saya, nilai
0
tidak "memperbaiki" masalah yang ditunjukkan oleh biola - 10. Saya sebenarnya agak terhalang oleh ini, karena menurut saya logis bahwa pesan pembaruan UI harus di-antri sebelum itu, karena pemicunya dieksekusi sebelum penjadwalan fungsi yang berjalan lama untuk dijalankan "nanti". Tapi mungkin ada beberapa optimisasi di mesin V8 yang dapat mengganggu, atau mungkin pemahaman saya kurang.Oke, jadi apa masalahnya dengan menggunakan
setTimeout
, dan apa solusi yang lebih baik untuk kasus khusus ini?Pertama, masalah dengan menggunakan
setTimeout
event handler seperti ini, untuk mencoba mengatasi masalah lain, cenderung berantakan dengan kode lain. Ini contoh nyata dari pekerjaan saya:Seorang kolega, dalam pemahaman yang salah informasi pada loop acara, mencoba "mengaitkan" Javascript dengan meminta beberapa kode rendering templat digunakan
setTimeout 0
untuk renderingnya. Dia tidak lagi di sini untuk bertanya, tetapi saya dapat berasumsi bahwa mungkin dia memasukkan timer untuk mengukur kecepatan rendering (yang akan menjadi kedekatan kembali fungsi) dan menemukan bahwa menggunakan pendekatan ini akan membuat respons yang sangat cepat dari fungsi itu.Masalah pertama sudah jelas; Anda tidak dapat mengaitkan javascript, jadi Anda tidak memenangkan apa pun di sini saat Anda menambahkan kebingungan. Kedua, Anda sekarang telah secara efektif memisahkan rendering templat dari tumpukan kemungkinan pendengar acara yang mungkin berharap bahwa templat yang telah dirender, meskipun mungkin tidak. Perilaku aktual dari fungsi itu sekarang non-deterministik, seperti - tanpa sadar begitu - fungsi apa pun yang akan menjalankannya, atau bergantung padanya. Anda dapat membuat tebakan yang terpelajar, tetapi Anda tidak dapat membuat kode yang benar untuk perilakunya.
"Memperbaiki" saat menulis event handler baru yang bergantung pada logikanya juga digunakan
setTimeout 0
. Tapi, itu bukan perbaikan, sulit untuk dipahami, dan tidak menyenangkan untuk men-debug kesalahan yang disebabkan oleh kode seperti ini. Kadang-kadang tidak ada masalah, di lain waktu itu gagal secara konsisten, dan sekali lagi, kadang-kadang ia bekerja dan rusak secara sporadis, tergantung pada kinerja platform saat ini dan apa pun yang terjadi pada saat itu. Inilah mengapa saya pribadi menyarankan untuk tidak menggunakan hack ini (ini adalah hack, dan kita semua harus tahu itu), kecuali Anda benar-benar tahu apa yang Anda lakukan dan apa konsekuensinya.Tapi apa yang bisa kita lakukan? Yah, seperti yang disarankan oleh artikel MDN yang direferensikan, pisahkan pekerjaan menjadi beberapa pesan (jika Anda bisa) sehingga pesan lain yang di-antri dapat disatukan dengan pekerjaan Anda dan dieksekusi saat dijalankan, atau menggunakan pekerja web, yang dapat menjalankan bersama-sama dengan halaman Anda dan mengembalikan hasil ketika dilakukan dengan perhitungannya.
Oh, dan jika Anda berpikir, "Yah, tidak bisakah saya melakukan panggilan balik pada fungsi yang sudah berjalan lama untuk menjadikannya tidak sinkron ?," lalu tidak. Callback tidak menjadikannya tidak sinkron, itu masih harus menjalankan kode yang sudah berjalan lama sebelum secara eksplisit memanggil panggilan balik Anda.
sumber
Hal lain yang dilakukan adalah mendorong pemanggilan fungsi ke bagian bawah tumpukan, mencegah tumpukan meluap jika Anda secara berulang memanggil suatu fungsi. Ini memiliki efek
while
loop tetapi membiarkan mesin JavaScript menyalakan timer asinkron lainnya.sumber
push the function invocation to the bottom of the stack
. Apastack
yang Anda bicarakan tidak jelas. Yang terpenting adalah di mana tepatnyasetTimeout
menambahkan fungsi ini, akhir dari siklus loop ini atau sangat awal siklus loop berikutnya.Dengan memanggil setTimeout Anda memberi waktu pada halaman untuk bereaksi terhadap apa pun yang dilakukan pengguna. Ini sangat membantu untuk fungsi yang dijalankan selama pemuatan halaman.
sumber
Beberapa kasus lain di mana setTimeout berguna:
Anda ingin memecah loop yang sudah berjalan lama atau perhitungan menjadi komponen yang lebih kecil sehingga browser tidak tampak 'membeku' atau mengatakan "Script pada halaman sedang sibuk".
Anda ingin menonaktifkan tombol kirim formulir ketika diklik, tetapi jika Anda menonaktifkan tombol di pengendali onClick formulir tidak akan dikirimkan. setTimeout dengan waktu nol berfungsi, membiarkan acara berakhir, formulir untuk mulai mengirimkan, lalu tombol Anda dapat dinonaktifkan.
sumber
Jawaban tentang loop eksekusi dan rendering DOM sebelum beberapa kode lainnya selesai benar. Nol timeout kedua dalam JavaScript membantu membuat kode pseudo-multithreaded, meskipun tidak.
Saya ingin menambahkan bahwa nilai TERBAIK untuk lintas peramban / lintas platform batas waktu nol detik dalam JavaScript sebenarnya sekitar 20 milidetik alih-alih 0 (nol), karena banyak peramban seluler tidak dapat mendaftarkan batas waktu lebih kecil dari 20 milidetik karena keterbatasan jam pada chip AMD.
Selain itu, proses jangka panjang yang tidak melibatkan manipulasi DOM harus dikirim ke Pekerja Web sekarang, karena mereka memberikan eksekusi benar-benar multithreaded JavaScript.
sumber
setTimout pada 0 juga sangat berguna dalam pola pengaturan janji yang ditangguhkan, yang ingin segera Anda kembalikan:
sumber
Masalahnya adalah Anda mencoba melakukan operasi Javascript pada elemen yang tidak ada. Elemen belum dimuat dan
setTimeout()
memberi lebih banyak waktu bagi elemen untuk memuat dengan cara berikut:setTimeout()
menyebabkan acara menjadi ansinkron karena itu dijalankan setelah semua kode sinkron, memberikan elemen Anda lebih banyak waktu untuk memuat. Panggilan balik yang tidak sinkron seperti panggilan baliksetTimeout()
ditempatkan di antrian acara dan diletakkan di tumpukan oleh loop acara sinkron setelah tumpukan kode sinkron kosong.setTimeout()
seringkali sedikit lebih tinggi (4-10 ms tergantung pada browser). Waktu yang sedikit lebih tinggi ini diperlukan untuk menjalankansetTimeout()
callback disebabkan oleh jumlah 'ticks' (di mana sebuah tick mendorong callback pada stack jika stack kosong) dari loop acara. Karena alasan kinerja dan usia baterai, jumlah kutu dalam loop aktivitas dibatasi hingga jumlah tertentu kurang dari 1000 kali per detik.sumber
Javascript adalah aplikasi berulir tunggal sehingga tidak memungkinkan untuk menjalankan fungsi secara bersamaan sehingga untuk mencapai hal ini loop digunakan. Jadi persis apa yang dilakukan setTimeout (fn, 0) dengan tugas pencarian yang dijalankan ketika tumpukan panggilan Anda kosong. Saya tahu penjelasan ini cukup membosankan, jadi saya sarankan Anda membaca video ini karena ini akan membantu Anda bagaimana berbagai hal bekerja di bawah kap browser. Lihat video ini: - https://www.youtube.com/watch?time_continue=392&v=8aGhZQkoFbQ
sumber