Bagaimana cara menjalankan loop asinkron secara berurutan atau paralel dalam JavaScript?
Sebelum melakukan sihir asinkron, saya ingin mengingatkan Anda seperti apa loop sinkron klasik itu.
Loop sinkron
Beberapa waktu yang lalu saya menulis loop dengan cara ini (mungkin Anda juga):
for (var i=0; i < array.length; i++) { var item = array[i];
Siklus ini baik dan cepat. Tetapi dia memiliki banyak masalah dengan keterbacaan dan dukungan. Setelah beberapa saat, saya terbiasa dengan versi terbaiknya:
array.forEach((item) => {
JavaScript berkembang sangat cepat. Fitur dan sintaks baru muncul. Salah satu perangkat tambahan favorit saya adalah async / menunggu .
Sekarang saya cukup sering menggunakan sintaks ini. Dan kadang-kadang ada situasi ketika saya perlu melakukan sesuatu dengan elemen array secara asinkron.
Loop asinkron
Bagaimana cara menggunakan await
di badan loop? Mari kita coba menulis fungsi asinkron dan mengharapkan tugas memproses setiap elemen:
async function processArray(array) { array.forEach(item => {
Kode ini akan menimbulkan kesalahan. Mengapa Karena kita tidak dapat menggunakan await
di dalam fungsi sinkron. Seperti yang Anda lihat, processArray
adalah fungsi asinkron. Tetapi fungsi anonim yang kami gunakan untuk forEach
adalah sinkron .
Apa yang bisa dilakukan tentang ini?
1. Jangan menunggu hasil eksekusi
Kita dapat mendefinisikan fungsi anonim sebagai asinkron:
async function processArray(array) { array.forEach(async (item) => { await func(item); }) console.log('Done!'); }
Tetapi forEach
tidak akan menunggu tugas selesai. forEach
adalah operasi yang sinkron. Dia hanya akan memulai tugas dan melanjutkan. Mari kita periksa tes sederhana:
function delay() { return new Promise(resolve => setTimeout(resolve, 300)); } async function delayedLog(item) {
Di konsol kita akan melihat:
Done! 1 2 3
Dalam beberapa situasi, ini mungkin hasil yang normal. Tapi tetap saja, dalam banyak kasus ini bukan logika yang cocok.
2. Memproses siklus secara berurutan
Untuk menunggu hasil dari eksekusi loop body, kita perlu kembali ke loop "for" lama yang baik. Tapi kali ini kita akan menggunakan versi barunya dengan for..of
construct (Terima kasih kepada Iteration Protocol ):
async function processArray(array) { for (const item of array) { await delayedLog(item); } console.log('Done!'); }
Ini akan memberi kami hasil yang diharapkan:
1 2 3 Done!
Setiap elemen array akan diproses secara berurutan. Tapi kita bisa menjalankan loop secara paralel!
3. Memproses loop secara paralel
Anda perlu sedikit memodifikasi kode untuk memulai operasi secara paralel:
async function processArray(array) {
Kode ini dapat menjalankan beberapa tugas delayLog
secara paralel. Tapi hati-hati dengan array besar. Terlalu banyak tugas bisa terlalu sulit untuk CPU dan memori.
Juga, tolong jangan membingungkan "tugas paralel" dari contoh dengan paralelisme nyata dan utas. Kode ini tidak menjamin eksekusi paralel. Semuanya tergantung pada tubuh loop (dalam contoh, itu adalah delayedLog
). Permintaan jaringan, pekerja web, dan beberapa tugas lain dapat dilakukan secara paralel.