JavaScript utas tunggal
Threading tunggal Javascript terkait dengan tujuannya. Sebagai bahasa skrip browser, tujuan utama JavaScript adalah untuk berinteraksi dengan pengguna dan mengoperasikan DOM. Ini menentukan bahwa itu hanya dapat berulir tunggal, jika tidak, ia akan menyebabkan masalah sinkronisasi yang sangat kompleks. Misalnya, misalkan JavaScript memiliki dua utas secara bersamaan, satu utas menambahkan konten pada simpul DOM tertentu, dan utas lainnya menghapus node ini, utas mana yang harus diambil browser saat ini? Oleh karena itu, untuk menghindari kompleksitas, JavaScript adalah satu utas dari kelahirannya, yang telah menjadi fitur inti dari bahasa ini dan tidak akan berubah di masa depan.
Tugas antrian
Single Threading berarti bahwa semua tugas perlu antri, dan tugas sebelumnya akan dieksekusi sebelum tugas berikutnya akan dieksekusi. Jika tugas sebelumnya membutuhkan waktu lama, tugas selanjutnya harus menunggu.
Pengemudi Acara Asynchronous
Banyak perilaku di browser tidak disinkronkan, seperti: acara klik mouse, acara seret ukuran jendela, acara pemicu timer, callback penyelesaian xmlhttpRequest, dll. Ketika peristiwa asinkron terjadi, ia memasuki antrian acara. Browser memiliki loop pesan besar internal, loop peristiwa, yang akan menerbitkan antrian acara besar dan proses proses. Misalnya, browser saat ini sibuk memproses acara OnClick, dan kemudian peristiwa lain terjadi (seperti window onsize), dan acara asinkron ini dimasukkan ke dalam antrian acara dan menunggu untuk diproses. Acara ini akan dieksekusi hanya ketika pemrosesan sebelumnya selesai dan gratis.
Loop acara
JavaScript adalah satu-utara, tetapi browsernya tidak berhadapan tunggal
Browser akan memiliki setidaknya beberapa proses berikut
1. Browser GUI Rendering Thread
2. Utas mesin javascript
3. Browser Timeed Trigger Thread
4. Acara browser memicu utas
5. Browser HTTP Asynchronous Request Thread
Karena mesin JavaScript adalah single-threaded, kode pertama kali ditekan ke antrian dan kemudian dijalankan oleh mesin dengan cara pertama di pertama. Fungsi penanganan acara dan fungsi eksekusi timer juga akan ditempatkan dalam antrian ini, dan kemudian menggunakan loop tak terbatas untuk terus mengekstrak fungsi dari kepala tim untuk dieksekusi. Ini adalah Loop Acara.
Singkatnya, JS saling berhadapan, tetapi browsernya multi-threaded. Saat menemukan hal -hal yang tidak sinkron, browser akan memasukkan panggilan balik asinkron ke loop acara. Ketika utas JS tidak sibuk, baca loop acara.
Prinsip pengatur waktu
Cara menggunakan timer
setTimeout (fn, tunda)
setInterval (fn, tunda)
FN adalah fungsi atau string, penundaan adalah waktu penundaan, unit adalah milidetik
Ada hal -hal berikut yang perlu diperhatikan
1. Meskipun FN bisa menjadi string, tidak pernah disarankan untuk menggunakannya seperti ini.
2. Jika ada fungsi ini di FN, ini akan menunjuk ke jendela saat mengeksekusi.
Jika Anda memahami utas tunggal JS dan loop acara dengan baik, prinsip timer akan mudah dimengerti.
Jika pengatur waktu ditetapkan, ketika waktu tunda tercapai, browser akan memasukkan acara eksekusi yang tertunda ke loop acara. Saat waktunya habis, jika utas JS menganggur, itu akan dieksekusi (jadi akurasi timer tidak akurat)
Saya membaca artikel tentang perbedaan antara SetTimeout dan SetInterval yang selalu melakukan pemungutan suara. Kodenya adalah sebagai berikut
Salinan kode adalah sebagai berikut:
setTimeout (function () {
setTimeout (Arguments.Callee, 100)
}, 100)
setInterval (function () {}, 1000)
Arti umum dari artikel ini adalah bahwa SetTimeout memulai timer berikutnya setelah fungsi callback dieksekusi, sehingga harus dieksekusi pada interval, sementara SetInterval dieksekusi sepanjang waktu. Jika Anda menemukan utas JS yang terus mengeksekusi, Anda dapat menambahkan beberapa panggilan balik di loop acara. Ketika utas JS tidak sibuk, beberapa eksekusi akan dieksekusi satu demi satu.
Setelah pengujian, ditemukan bahwa SetInterval berada pada interval tertentu, tidak peduli di bawah IE, FF, Chrome, Opera, dan Safari.
Kode tes adalah sebagai berikut
Salinan kode adalah sebagai berikut:
setInterval (function () {
xx.innerhtml = xx.innerHtml+1;
}, 100);
untuk (var i = 0; i <6000000; i ++) {
xx.offsetwidth
}
setTimeout (function () {
debugger;
}, 10)
Saat breakpoint masih dicetak hanya 1
Masalah akurasi pengatur waktu
Karena utas tunggal JS, jika Anda mengalami kesibukan, timer pasti akan tidak akurat, dan itu pasti akan lebih lama dan lebih lama. Ini tampaknya tidak dapat diselesaikan, tidak ada solusi.
Masalah akurasi lainnya adalah penyelesaian interval minimum (menyenangkan, 0)
Ketika utas JS tidak sibuk, tidak mungkin untuk dieksekusi segera setelah 0 detik. Selalu ada interval minimum, dan setiap browser masih berbeda. Ini belum diuji.
Saya membaca artikel tentang standar W3C. Eksekusi waktu minimum timer adalah 4ms. Tidak ada cara untuk memverifikasi sumber jika Anda tidak dapat menemukannya! Lai Lai
Beberapa optimisasi yang terkait dengan pengatur waktu
Masih ada beberapa optimisasi saat membuat timer
1. Misalnya, jika Anda mengikat jendela. Menghubungkan, pemicu akan sangat sering ketika browser diperbesar, sehingga Anda dapat menunda eksekusi. Ketika eksekusi berikutnya dibersihkan, itu akan mengurangi eksekusi yang sering.
Kode pseudo adalah sebagai berikut
Salinan kode adalah sebagai berikut:
var timer;
fungsi r () {
ClearTimeout (timer);
timer = setTimeout (function () {
// Lakukan sesuatu
}, 150);
}
2. Ketika bilah gulir ditarik ke bawah, itu juga sedikit. Misalnya, malas gambar juga harus memiliki timer untuk menghindari perhitungan yang berlebihan.
3. Ketika ada beberapa tempat di mana timer dibutuhkan, Anda dapat menggabungkannya menjadi timer. Interval waktu adalah yang terkecil. Kemudian fungsi panggilan balik yang perlu dieksekusi dimasukkan ke dalam array. Ketika interval waktu tercapai, beralih melalui array untuk dieksekusi.
Demo kecil
Salinan kode adalah sebagai berikut:
<! Doctype html>
<Html>
<head>
<meta charset = "UTF-8" />
<tyle>
.wrap {lebar: 80%; Margin: 30px Auto; Perbatasan: 1px solid #ccc; padding: 20px;}
.c {border: 1px solid #ccc; Tinggi: 30px; margin-bottom: 20px;}
</tyle>
</head>
<body>
<Div id = "xx"> </div>
<div>
<Div ID = "A1"> 0 </div>
<Div ID = "A2"> 0 </div>
<Div ID = "A3"> 0 </div>
<Div ID = "A4"> 0 </div>
</div>
<Script src = "http://static.paipaiimg.com/paipai_h5/js/ttj/zepto.min.js"> </script>
<type skrip = "Teks/JavaScript">
var runtime = {
Opsi: {
Langkah: 1000
},
Callbacks: [],
addCallbacks: [],
Mulai: Salah,
Timer: NULL,
Extens: function () {
var target = argumen [0] || {}, i = 1, panjang = argumen.length, opsi;
if (typeof target! = "objek" && typeof target! = "function")
target = {};
untuk (; i <panjang; i ++)
if ((options = argumen [i])! = null)
untuk (nama var di opsi) {
var copy = options [name];
if (target === salin)
melanjutkan;
if (copy! == tidak ditentukan)
target [name] = copy;
}
target pengembalian;
},
init: function (option) {
$ .Extend (this, this.options, options || {});
},
tambahkan: function (fun, options) {
opsi = option || {};
this.addcallbacks.push ({
Menyenangkan: Menyenangkan,
StartTime: Tanggal baru (). GetTime (),
Langkah: Options.Step || this.step,
I: 1
});
var self = ini;
if (! this.start) {
this.callbacks = [fun];
this.start = true;
this.starttime = tanggal baru (). getTime ();
this.timer = setInterval (function () {
self.done ();
}, this.step);
}
},
selesai: function () {
var callbacks = this.callbacks,
self = ini,
newarr = [];
$ .each (callbacks, function (i, obj) {
if (obj.step == self.step) {
obj.fun ();
}kalau tidak{
if (obj.i == obj.step/self.step) {
if ((new date (). getTime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
}
obj.i = 1;
}kalau tidak{
obj.i = obj.i + 1;
}
}
});
$ .each (this.addcallbacks, function (i, obj) {
if (obj.step == self.step) {
if ((new date (). getTime ())-obj.starttime> obj.step*2/3) {
obj.fun ();
callbacks.push (OBJ);
}kalau tidak{
newarr.push (OBJ);
}
}kalau tidak{
obj.i = obj.i + 1;
callbacks.push (OBJ);
}
});
this.addcallbacks = newarr;
},
CLEAR: function () {
clearInterval (this.timer);
}
}
runtime.init ();
runtime.add (function () {
a1.innerHtml = ~~ a1.innerHtml+1;
});
runtime.add (function () {
a2.innerHtml = ~~ a2.innerhtml+1;
}, {langkah: 2000});
runtime.add (function () {
a3.innerHtml = ~~ a3.innerHtml+1;
}, {langkah: 4000});
runtime.add (function () {
A4.InnerHtMl = ~~ A4.InnerHtMl+1;
}, {Langkah: 8000});
</script>
</body>
</html>
Apakah Anda tahu tentang Timer JavaScript? Tinggalkan saya pesan jika Anda memiliki pertanyaan.