Seperti yang Anda ketahui, lingkungan eksekusi bahasa JavaScript adalah "utas tunggal".
Yang disebut "utas tunggal" berarti bahwa satu tugas hanya dapat diselesaikan sekaligus. Jika ada beberapa tugas, Anda harus mengantri, menyelesaikan tugas sebelumnya, menjalankan tugas berikutnya, dan sebagainya.
Keuntungan dari model ini adalah relatif sederhana untuk diterapkan dan lingkungan eksekusi relatif sederhana; Kerugiannya adalah bahwa selama ada tugas yang membutuhkan waktu lama, tugas -tugas selanjutnya harus diantri, yang akan menunda pelaksanaan seluruh program. Browser umum tidak responsif (kematian palsu) sering karena sepotong kode JavaScript tertentu berjalan untuk waktu yang lama (seperti loop mati), menyebabkan seluruh halaman macet di tempat ini dan tugas -tugas lain tidak dapat dieksekusi.
Untuk mengatasi masalah ini, bahasa JavaScript membagi mode eksekusi tugas menjadi dua jenis: sinkron (sinkron) dan asinkron (asinkron).
"Mode Sinkron" adalah pola bagian sebelumnya. Tugas terakhir menunggu tugas sebelumnya berakhir dan kemudian dieksekusi. Urutan eksekusi program konsisten dan sinkron dengan urutan pengaturan tugas; "Mode asinkron" sangat berbeda. Setiap tugas memiliki satu atau lebih fungsi panggilan balik (panggilan balik). Setelah tugas sebelumnya selesai, ini bukan tugas berikutnya, tetapi fungsi panggilan balik dijalankan. Tugas terakhir dieksekusi tanpa menunggu tugas sebelumnya berakhir, sehingga urutan eksekusi program tidak konsisten dan tidak sinkron dengan urutan pengaturan tugas.
"Mode async" sangat penting. Di sisi browser, operasi jangka panjang harus dieksekusi secara tidak sinkron untuk menghindari browser dari kehilangan respons. Contoh terbaik adalah operasi AJAX. Di sisi server, "Mode Asynchronous" bahkan adalah satu-satunya mode, karena lingkungan eksekusi adalah satu utamanya, jika semua permintaan HTTP diizinkan untuk dieksekusi secara serempak, kinerja server akan turun dengan tajam dan akan segera kehilangan tanggapannya.
Artikel ini merangkum 4 metode pemrograman "mode asinkron". Memahami mereka memungkinkan Anda untuk menulis program JavaScript dengan struktur yang lebih masuk akal, kinerja yang lebih baik, dan pemeliharaan yang lebih nyaman.
1. Fungsi panggilan balik
Ini adalah metode paling mendasar dari pemrograman asinkron.
Asumsikan ada dua fungsi F1 dan F2, yang terakhir menunggu hasil eksekusi yang pertama.
Salinan kode adalah sebagai berikut:
f1 ();
f2 ();
Jika F1 adalah tugas yang memakan waktu, Anda dapat mempertimbangkan untuk menulis ulang F1 dan menulis F2 sebagai fungsi callback F1.
Salinan kode adalah sebagai berikut:
fungsi f1 (callback) {
setTimeout (function () {
// kode tugas F1
callback ();
}, 1000);
}
Kode eksekusi menjadi seperti ini:
Salinan kode adalah sebagai berikut:
f1 (f2);
Dengan cara ini, kami mengubah operasi sinkron menjadi operasi asinkron. F1 tidak akan memblokir operasi program, yang setara dengan melaksanakan logika utama program terlebih dahulu dan menunda pelaksanaan operasi yang memakan waktu.
Keuntungan dari fungsi callback adalah bahwa mereka sederhana, mudah dimengerti dan digunakan, dan kerugiannya adalah bahwa mereka tidak kondusif untuk membaca dan pemeliharaan kode. Mereka sangat digabungkan (kopling) antara berbagai bagian, dan prosesnya akan sangat kacau, dan setiap tugas hanya dapat menentukan satu fungsi panggilan balik.
2. Pemantauan acara
Gagasan lain adalah mengadopsi model yang digerakkan oleh acara. Eksekusi tugas tidak tergantung pada urutan kode, tetapi pada apakah suatu peristiwa terjadi.
Mari kita ambil F1 dan F2 sebagai contoh. Pertama, ikat acara untuk F1 (metode penulisan jQuery yang digunakan di sini).
Salinan kode adalah sebagai berikut:
f1.on ('selesai', f2);
Baris kode di atas berarti bahwa ketika acara selesai terjadi di F1, F2 dieksekusi. Kemudian, tulis ulang F1:
Salinan kode adalah sebagai berikut:
fungsi f1 () {
setTimeout (function () {
// kode tugas F1
f1.trigger ('selesai');
}, 1000);
}
f1.trigger ('selesai') berarti bahwa setelah eksekusi selesai, acara selesai segera dipicu, dengan demikian mulai mengeksekusi F2.
Keuntungan dari metode ini adalah relatif mudah dimengerti. Ini dapat mengikat beberapa acara, dan setiap acara dapat menentukan beberapa fungsi panggilan balik, dan dapat "decoupling", yang kondusif untuk modularisasi. Kerugiannya adalah bahwa seluruh program akan menjadi berbasis peristiwa, dan proses operasi akan menjadi sangat tidak jelas.
3. Publikasikan/Berlangganan
"Acara" di bagian sebelumnya dapat sepenuhnya dipahami sebagai "sinyal".
Kami berasumsi bahwa ada "pusat sinyal". Setelah tugas selesai, sinyal diterbitkan ke pusat sinyal. Tugas lain dapat "berlangganan" sinyal ke pusat sinyal, sehingga dapat mengetahui kapan itu dapat memulai eksekusi. Ini disebut "Pola Berlangganan Publikasikan", juga dikenal sebagai "Pola Pengamat".
Ada banyak implementasi model ini. Berikut ini adalah Ben Alman's Tiny Pub/Sub, yang merupakan plug-in untuk jQuery.
Pertama, F2 berlangganan sinyal "Selesai" ke jQuery "Sinyal Center".
Salinan kode adalah sebagai berikut:
jQuery.subscribe ("Done", F2);
Kemudian, F1 ditulis ulang sebagai berikut:
Salinan kode adalah sebagai berikut:
fungsi f1 () {
setTimeout (function () {
// kode tugas F1
jQuery.publish ("selesai");
}, 1000);
}
jQuery.publish ("Done") berarti bahwa setelah eksekusi F1 selesai, sinyal "selesai" dikeluarkan untuk jQuery "Center Sinyal", sehingga memicu eksekusi F2.
Selain itu, setelah F2 dieksekusi, berhenti berlangganan juga dapat tidak berlangganan.
Salinan kode adalah sebagai berikut:
jQuery.unsubscribe ("selesai", f2);
Sifat metode ini mirip dengan "mendengarkan peristiwa", tetapi secara signifikan lebih baik daripada yang terakhir. Karena kita dapat memantau pengoperasian program dengan melihat "pusat pesan" untuk memahami berapa banyak sinyal yang ada dan berapa banyak pelanggan untuk setiap sinyal.
4. Janji Objek
Objek janji adalah spesifikasi yang diusulkan oleh kelompok kerja CommonJS, dengan tujuan menyediakan antarmuka terpadu untuk pemrograman asinkron.
Sederhananya, idenya adalah bahwa setiap tugas asinkron mengembalikan objek janji, yang memiliki metode kemudian yang memungkinkan fungsi callback ditentukan. Misalnya, fungsi panggilan balik F2 dari F1 dapat ditulis sebagai:
Salinan kode adalah sebagai berikut:
f1 (). Kemudian (f2);
F1 perlu ditulis ulang sebagai berikut (implementasi jQuery digunakan di sini):
Salinan kode adalah sebagai berikut:
fungsi f1 () {
var dfd = $ .deferred ();
setTimeout (function () {
// kode tugas F1
dfd.resolve ();
}, 500);
return dfd.promise;
}
Keuntungan menulis dengan cara ini adalah bahwa fungsi callback telah menjadi metode penulisan rantai, dan aliran program dapat dilihat dengan sangat jelas, dan ada serangkaian metode pendukung lengkap yang dapat mewujudkan banyak fungsi yang kuat.
Misalnya, tentukan beberapa fungsi panggilan balik:
Salinan kode adalah sebagai berikut:
f1 (). Kemudian (f2) .then (f3);
Misalnya, tentukan fungsi callback saat kesalahan terjadi:
Salinan kode adalah sebagai berikut:
f1 (). Kemudian (f2) .fail (f3);
Selain itu, ia memiliki keuntungan yang tidak dimiliki oleh tidak satu pun dari tiga metode sebelumnya: jika suatu tugas telah selesai, tambahkan fungsi panggilan balik, dan fungsi panggilan balik akan segera dieksekusi. Jadi, Anda tidak perlu khawatir kehilangan suatu acara atau sinyal. Kerugian dari metode ini adalah relatif sulit untuk ditulis dan dipahami.