Walau bagaimanapun, apa yang boleh kita lakukan ialah
mensimulasikanmulti-threading, sejauh ia menimbulkan salah satu manfaat persekitaran pelbagai threaded: ia membolehkan kita menjalankan kod yang sangat intensif. Ini adalah kod yang sebaliknya akan membekukan penyemak imbas dan menghasilkan salah satu daripada "skrip tidak responsif" amaran di Firefox. Kunci Takeaways
kali secepat mungkin." Walau bagaimanapun kod yang sama di dalam pemasa tak segerak adalah memecahkan kod ke dalam ketulan kecil yang bijak; iaitu, "Jalankan kod ini sekali sebaik mungkin," - kemudian tunggu - kemudian "jalankan kod ini secepat mungkin", dan sebagainya,
n kali.
Caranya ialah kod di dalam setiap lelaran adalah kecil dan cukup mudah untuk penterjemah untuk memprosesnya sepenuhnya dalam kelajuan pemasa, sama ada 100 atau 5,000 milisaat. Sekiranya keperluan itu dipenuhi, maka tidak kira betapa kuatnya kod keseluruhannya, kerana kami tidak meminta ia dijalankan sekaligus. Biasanya, jika saya menulis skrip yang terbukti terlalu intensif, saya akan melihat semula kejuruteraannya; Kelembapan yang signifikan biasanya menunjukkan masalah dengan kod, atau masalah yang lebih mendalam dengan reka bentuk aplikasi. Tetapi kadang -kadang tidak. Kadang -kadang tidak ada cara untuk mengelakkan intensiti operasi tertentu, kekurangan tidak melakukannya dalam JavaScript sama sekali. yang mungkin penyelesaian terbaik dalam kes tertentu; Mungkin beberapa pemprosesan dalam aplikasi perlu dipindahkan ke sisi pelayan, di mana ia mempunyai lebih banyak kuasa pemprosesan untuk bekerja dengan, secara amnya, dan persekitaran pelaksanaan yang benar-benar berulir (pelayan web). Tetapi akhirnya anda mungkin mendapati situasi di mana itu bukan pilihan - di mana JavaScript hanya mesti dapat melakukan sesuatu, atau dihukum. Itulah keadaan yang saya dapati ketika membangunkan lanjutan Firefox saya, pemilih debu-saya. Inti pelanjutan itu adalah keupayaan untuk menguji pemilih CSS yang digunakan pada halaman, untuk melihat sama ada mereka sebenarnya digunakan. Intipati ini adalah satu set penilaian menggunakan kaedah Matchall () dari Dean Edwards 'Base2: cukup mudah, pasti. Tetapi Matchall () sendiri cukup sengit, mempunyai - seperti yang dilakukan - untuk menghuraikan dan menilai mana -mana pemilih CSS1 atau CSS2, kemudian berjalan seluruh Pokok Dom mencari perlawanan; dan lanjutannya untuk setiap pemilih individu , yang mana mungkin terdapat beberapa ribu. Proses itu, di permukaan begitu mudah, boleh menjadi begitu intensif sehingga seluruh penyemak imbas membeku semasa ia berlaku. Dan inilah yang kita dapati. Mengunci penyemak imbas jelas bukan pilihan, jadi jika ini berfungsi sama sekali, kita mesti mencari cara untuk membuatnya berjalan tanpa kesilapan. mari kita tunjukkan masalah dengan kes ujian mudah yang melibatkan dua tahap lelaran; Tahap dalaman sengaja terlalu intensif supaya kita dapat mewujudkan keadaan perlumbaan, sementara tahap luar agak pendek sehingga ia mensimulasikan kod utama. Inilah yang kita ada: Kami memulakan ujian kami, dan mendapatkan output kami, dari bentuk mudah (ini adalah kod ujian, bukan pengeluaran, jadi maafkan saya untuk menggunakan pengendali acara inline): Sekarang mari kita jalankan kod itu di Firefox (dalam kes ini, Firefox 3 pada MacBook 2GHz) ... dan seperti yang dijangkakan, penyemak imbas UI membeku semasa ia berjalan (menjadikannya mustahil, sebagai contoh, untuk menekan semula dan meninggalkan prosesnya) . Selepas kira -kira 90 lelaran, Firefox menghasilkan dialog amaran "skrip tidak responsif". Safari 3 dan Internet Explorer 6 berkelakuan sama dalam hal ini, dengan UI beku dan ambang di mana dialog amaran dihasilkan. Di Opera tidak ada dialog sedemikian - ia terus menjalankan kod sehingga ia selesai - tetapi UI penyemak imbas juga dibekukan sehingga tugas selesai. Jelas sekali kita tidak dapat menjalankan kod seperti itu dalam amalan. Oleh itu mari kita buat semula dan gunakan pemasa tak segerak untuk gelung luar: Sekarang mari kita jalankan lagi ... dan kali ini kita menerima hasil yang sama sekali berbeza. Kod ini mengambil sedikit masa untuk disiapkan, pasti, tetapi ia berjalan dengan jayanya sepanjang jalan hingga akhir, tanpa pembekuan UI dan tanpa amaran tentang skrip yang terlalu perlahan.
dalaman masih minimum, bilangan bilangan masa kita dapat menjalankan proses itu sekarang tidak terhad: kita dapat menjalankan Gelung luar pada dasarnya selama -lamanya, dan penyemak imbas tidak akan membeku.
permainan pada Untuk menggambarkan, saya akan melihat projek yang saya telah berkembang di sisi untuk seketika. Dengan "sedikit" saya maksudkan , majoriti yang dibelanjakan di dataran tinggi di mana permainan secara teorinya bekerja, tetapi terlalu sengit untuk digunakan ... sehingga saya memikirkan pendekatan ini. Permainan ini adalah teka-teki yang kompetitif berdasarkan warna dan pencocokan bentuk.
, masing -masing dipilih dengan pernyataan suis, dan berulang dengan menggunakan pemasa tak segerak. Logik ini bukan satu juta batu dari mereka yang memilih buku pengembaraan anda sendiri yang pernah saya miliki sebagai seorang kanak -kanak, di mana setiap tugas menyimpulkan dengan pilihan tugas selanjutnya, semuanya dalam masa nyata, sehingga kita sampai pada akhir:
Tetapi apa yang kita cuba lakukan di sini adalah mewujudkan persekitaran pelaksanaan tanpa siling, iaitu proses yang tidak mempunyai had atas dari segi kerumitan dan panjang; Dan itulah yang telah kami lakukan. Corak ini boleh dilanjutkan , dengan beratus -ratus atau bahkan beribu -ribu tugas. Ia mungkin mengambil masa yang lama untuk berlari, tetapi jalankan ia akan, dan selagi setiap individu tugas tidak terlalu sengit, ia akan berjalan tanpa membunuh penyemak imbas.
jalan tidak kembali yang menyentuh fungsi () akan selalu kembali palsu kerana fungsi dalaman tidak segerak. Fungsi luar akan kembali sebelum lelaran pertama fungsi dalaman telah berlaku! Contoh seterusnya ini juga sia -sia: Kami keluar dari skop fungsi luar, oleh itu kami tidak dapat kembali daripadanya; Nilai pulangan itu hilang dengan sia -sia ke dalam eter. apa yang kita boleh di sini adalah mengambil daun daripada teknik pengekodan Ajax, dan menggunakan fungsi panggilan balik (yang dalam contoh ini saya panggil "onComplete"): Jadi apabila kita memanggil Checksomething (), kita lulus fungsi tanpa nama sebagai hujahnya, dan fungsi itu dipanggil dengan nilai akhir apabila kerja selesai: elegan? Tidak. Tetapi berfungsi dengan kuat? Ya. Dan itulah maksudnya. Menggunakan teknik ini, kita boleh menulis skrip yang tidak mungkin. Dengan teknik ini dalam kit kami, kami kini mempunyai cara untuk menangani projek JavaScript yang sebelum ini keluar dari alam kemungkinan. Permainan yang saya buat corak ini mempunyai logik yang agak mudah, dan oleh itu otak yang agak mudah, tetapi ia masih terlalu banyak untuk lelaran konvensional; Dan terdapat banyak permainan lain di luar sana yang memerlukan lebih banyak pengaruh!
Jika anda suka membaca siaran ini, anda akan suka dipelajari; Tempat untuk mempelajari kemahiran dan teknik segar dari Sarjana. Ahli mendapat akses segera ke semua ebook SitePoint dan kursus dalam talian interaktif, seperti pengaturcaraan JavaScript untuk web.
Komen mengenai artikel ini ditutup. Ada soalan mengenai JavaScript? Mengapa tidak bertanya di forum kami?
Kredit Imej: Randen L Peterson
Untuk menggunakan pekerja web untuk multithreading dalam JavaScript, anda perlu membuat objek pekerja baru dan menentukan fail JavaScript untuk dilaksanakan dalam benang pekerja. Anda kemudian boleh berkomunikasi dengan benang pekerja menggunakan kaedah postmessage dan menerima mesej daripadanya menggunakan pengendali acara onMessage. betapa sengitnya "terlalu sengit"?
for(var i=0; i<selectors.length; i++) <br>
{ <br>
if(base2.DOM.Document.matchAll <br>
(contentdoc, selectors[i]).length > 0) <br>
{ <br>
used ++; <br>
} <br>
else <br>
{ <br>
unused ++; <br>
} <br>
}
kes ujian mudah
function process() <br>
{ <br>
var above = 0, below = 0; <br>
for(var i=0; i<200000; i++) <br>
{ <br>
if(Math.random() * 2 > 1) <br>
{ <br>
above ++; <br>
} <br>
else <br>
{ <br>
below ++; <br>
} <br>
} <br>
} <br>
<br>
<br>
function test1() <br>
{ <br>
var result1 = document.getElementById('result1'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
for(var i=0; i<200; i++) <br>
{ <br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
} <br>
<br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
}
<form action=""> <br>
<fieldset> <br>
<input type="button" value="test1" onclick="test1()" /> <br>
<input type="text" /> <br>
</fieldset> <br>
</form> <br>
Jika kita membenarkannya diteruskan, selepas 90 lelaran lain Firefox menghasilkan dialog yang sama sekali lagi. for(var i=0; i<selectors.length; i++) <br>
{ <br>
if(base2.DOM.Document.matchAll <br>
(contentdoc, selectors[i]).length > 0) <br>
{ <br>
used ++; <br>
} <br>
else <br>
{ <br>
unused ++; <br>
} <br>
}
Lihat halaman ujian
Saya dapat mendengar penentang sudah. Sebenarnya, saya boleh menjadi diri saya sendiri: Mengapa anda melakukan ini - apa jenis orang gila yang menegaskan untuk menolak JavaScript ke semua tempat ini yang tidak pernah dirancang untuk pergi? Kod anda terlalu sengit. Ini adalah alat yang salah untuk pekerjaan itu. Sekiranya anda perlu melompat melalui jenis gelung ini maka reka bentuk permohonan anda pada asasnya salah. Apa yang saya bicarakan di sini adalah kod yang diperlukan untuk memahami peraturan permainan, yang kemudiannya dapat menilai situasi dan taktik untuk cuba mengalahkan anda pada permainan itu. Barangan rumit.
Untuk meringkaskan: Anda membuat jalan anda di papan dengan bentuk bersebelahan dan padanan warna. Sebagai contoh, jika anda bermula, katakan, segitiga hijau - maka anda boleh berpindah ke segitiga lain, atau bentuk hijau yang lain. Objektif anda adalah untuk mencapai kristal di tengah, kemudian bawa ke sisi lain papan, sementara lawan anda cuba melakukan perkara yang sama. Anda juga boleh mencuri kristal dari lawan anda.
for(var i=0; i<selectors.length; i++) <br>
{ <br>
if(base2.DOM.Document.matchAll <br>
(contentdoc, selectors[i]).length > 0) <br>
{ <br>
used ++; <br>
} <br>
else <br>
{ <br>
unused ++; <br>
} <br>
}
function process() <br>
{ <br>
var above = 0, below = 0; <br>
for(var i=0; i<200000; i++) <br>
{ <br>
if(Math.random() * 2 > 1) <br>
{ <br>
above ++; <br>
} <br>
else <br>
{ <br>
below ++; <br>
} <br>
} <br>
} <br>
<br>
<br>
function test1() <br>
{ <br>
var result1 = document.getElementById('result1'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
for(var i=0; i<200; i++) <br>
{ <br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
} <br>
<br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
}
Kekuatan pendekatan ini juga kelemahan utamanya: kerana fungsi dalaman tidak segerak, kita tidak dapat mengembalikan nilai dari fungsi luar. Jadi, sebagai contoh, kita tidak boleh melakukan ini (atau sebaliknya, kita boleh, tetapi tidak akan ada gunanya):
for(var i=0; i<selectors.length; i++) <br>
{ <br>
if(base2.DOM.Document.matchAll <br>
(contentdoc, selectors[i]).length > 0) <br>
{ <br>
used ++; <br>
} <br>
else <br>
{ <br>
unused ++; <br>
} <br>
}
function process() <br>
{ <br>
var above = 0, below = 0; <br>
for(var i=0; i<200000; i++) <br>
{ <br>
if(Math.random() * 2 > 1) <br>
{ <br>
above ++; <br>
} <br>
else <br>
{ <br>
below ++; <br>
} <br>
} <br>
} <br>
<br>
<br>
function test1() <br>
{ <br>
var result1 = document.getElementById('result1'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
for(var i=0; i<200; i++) <br>
{ <br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
} <br>
<br>
result1.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
}
<form action=""> <br>
<fieldset> <br>
<input type="button" value="test1" onclick="test1()" /> <br>
<input type="text" /> <br>
</fieldset> <br>
</form> <br>
function test2() <br>
{ <br>
var result2 = document.getElementById('result2'); <br>
<br>
var start = new Date().getTime(); <br>
<br>
var i = 0, limit = 200, busy = false; <br>
var processor = setInterval(function() <br>
{ <br>
if(!busy) <br>
{ <br>
busy = true; <br>
<br>
result2.value = 'time=' + <br>
(new Date().getTime() - start) + ' [i=' + i + ']'; <br>
<br>
process(); <br>
<br>
if(++i == limit) <br>
{ <br>
clearInterval(processor); <br>
<br>
result2.value = 'time=' + <br>
(new Date().getTime() - start) + ' [done]'; <br>
} <br>
<br>
busy = false; <br>
} <br>
<br>
}, 100); <br>
<br>
}
Adakah Androids Dream of Silicon Sheep?
soalan yang sering ditanya mengenai multithreading dalam javascript
Apakah peranan pekerja web dalam multithreading JavaScript? Mereka adalah cara yang mudah untuk kandungan web untuk menjalankan skrip dalam benang latar belakang. Benang pekerja boleh melakukan tugas tanpa mengganggu antara muka pengguna. Di samping itu, mereka boleh melakukan I/O menggunakan XMLHTTPREQUEST (walaupun atribut Tindak Balas dan Saluran sentiasa NULL). Setelah dibuat, seorang pekerja boleh menghantar mesej ke kod JavaScript yang menciptanya dengan menghantar mesej kepada pengendali acara yang ditentukan oleh kod itu (dan sebaliknya). 🎜>
JavaScript sememangnya satu-threaded, tetapi ia boleh mengendalikan multithreading melalui penggunaan panggilan balik dan janji-janji yang tidak segerak. Ini bermakna bahawa walaupun JavaScript sendiri beroperasi pada satu benang, ia boleh menjadualkan tugas -tugas yang akan dilaksanakan pada masa akan datang, dengan berkesan membolehkannya melaksanakan pelbagai tugas serentak. Ini amat berguna untuk mengendalikan operasi seperti input pengguna atau permintaan API, yang boleh diproses di latar belakang manakala benang utama terus melaksanakan kod lain. 🎜> Walaupun multithreading dalam JavaScript boleh dicapai melalui pekerja web, penting untuk diperhatikan bahawa pekerja ini tidak mempunyai akses ke DOM atau API web lain. Mereka hanya terhad kepada beberapa jenis data yang boleh mereka hantar ke benang utama. Juga, setiap pekerja adalah contoh yang berasingan, jadi mereka tidak berkongsi skop atau mana-mana pembolehubah global. Dalam modul yang dipanggil 'cluster' yang membolehkan anda membuat proses kanak -kanak (pekerja), yang berkongsi port pelayan dengan proses nod utama (Master). Proses kanak-kanak ini boleh berjalan secara serentak dan berfungsi pada tugas yang berbeza, dengan berkesan melaksanakan multithreading. Isu dengan manipulasi data. Multithreading boleh membawa kepada masalah seperti keadaan kaum, di mana output bergantung kepada urutan atau masa peristiwa yang tidak terkawal lain. Ia dianggap lebih mudah untuk mengoptimumkan persekitaran tunggal, kerana tidak perlu menangani kebergantungan antara benang.
Bagaimana saya boleh menggunakan pekerja web untuk multithreading dalam javascript?
Bolehkah multithreading membuat kod javascript saya lebih cepat? Lebih cepat, tetapi ia bergantung kepada sifat tugas yang dilakukan. Untuk tugas-tugas intensif CPU, multithreading dapat meningkatkan prestasi dengan ketara dengan membenarkan tugas dilakukan secara selari. Walau bagaimanapun, untuk tugas-tugas I/O yang terikat, manfaat multithreading kurang jelas, kerana tugas-tugas ini sering dibatasi oleh faktor-faktor di luar kawalan CPU, seperti kelajuan rangkaian. Pengaturcaraan dalam JavaScript?
Pengaturcaraan multithreading dan asynchronous adalah kedua -dua teknik yang digunakan untuk menguruskan pelbagai tugas pada masa yang sama masa. Walau bagaimanapun, mereka melakukannya dengan cara yang berbeza. Multithreading melibatkan pelbagai benang pelaksanaan, dengan setiap benang melakukan tugas yang berbeza. Pengaturcaraan Asynchronous, sebaliknya, melibatkan satu benang pelaksanaan, tetapi tugas dapat dimulakan dan kemudian ditahan untuk diselesaikan kemudian, membolehkan tugas -tugas lain dilakukan dalam masa yang sama. Perkongsian data antara benang dalam JavaScript?
Atas ialah kandungan terperinci Multi-threading dalam JavaScript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!