Async: Async tidak melindungi dari modifikasi array selama runtime fungsi

Dibuat pada 4 Jul 2014  ·  6Komentar  ·  Sumber: caolan/async

Ketika Anda memiliki panggilan asinkron, mis. async.each , dan selama runtime itu, array yang diteruskan memiliki modifikasi, maka mungkin tidak akan pernah selesai, atau akan memanggil panggilan balik dua kali.

Contoh:

async = require "async" 
arr = [1, 2, 3]  
async.each arr, ((i, cb) -> console.log "i"; setImmediate(cb)), (err) -> console.log "done" 
arr.push(4)

Contoh ini mengulang melalui 3 elemen array asli, dan mencetak i tetapi kemudian tidak pernah memanggil panggilan balik, karena dalam async.each ia melakukan:

if (completed >= arr.length) {
  callback(null);
}

Saat melihat kode async, ia melakukan perbandingan terhadap arr.length yang dapat berubah...bukankah lebih baik untuk menyimpan panjang array asli dan melakukan perbandingan terhadap itu, memastikan bahwa panggilan balik yang telah selesai akan dipanggil ?

Biola:
http://jsfiddle.net/4ysKX/1/

bug

Komentar yang paling membantu

Apakah async akhirnya melarang modifikasi array setelah fakta? Saya memiliki kasus penggunaan di mana akan menyenangkan untuk memodifikasi array asli setelah fakta, untuk beralih pada lebih banyak elemen daripada awalnya.

Semua 6 komentar

Anda benar -- jadi jangan diubah. Kloning array Anda sebelum Anda meneruskannya ke fungsi async jika Anda perlu mengubahnya nanti.

@aearly Ya, itu solusi, tetapi masalah mendasar di sini adalah kesalahan yang sangat mudah dibuat, dan masalah yang sangat sulit untuk di-debug, jadi IMHO itu harus diperbaiki di perpustakaan inti. Ini telah menggigit saya dua kali sekarang pada dua proyek yang berbeda.

Akan sulit untuk melindungi dari modifikasi array _any_ tanpa mengkloning input, misalnya modifikasi sinkron dalam fungsi iterator, tetapi melindungi dari modifikasi _asynchronous_ yang tidak terkait dengan iterasi harus langsung dilakukan bahkan tanpa kloning -- benar-benar tidak mengasumsikan arr.length akan tetap konstan setelah menjalankan pekerjaan async (menyimpan panjang dalam variabel sebelum iterasi).

(Saya bekerja dengan @bradens -- salah satu dari kami akan mengirimkan PR dengan tes jika itu diterima).

PR dengan tes akan diterima, tetapi pada akhirnya terserah @caolan untuk menggabungkannya.

Kelemahan untuk melakukan ini adalah overhead ekstra dari penyalinan array. Jika Anda memiliki array yang besar, atau memanggil async.each dkk berkali-kali, itu akan menjadi lebih lambat dan menggunakan lebih banyak memori.

Saya setuju bahwa salinan array akan terlalu banyak overhead. Saya menyarankan bahwa karena iterasi awal array sinkron, panjang array asli dapat disimpan untuk diperiksa nanti. Dengan begitu, jumlah panggilan balik akan sesuai dengan jumlah panggilan iterator, bahkan jika array diubah sementara itu. Ini seharusnya mudah dan nol overhead untuk async.each , tetapi saya belum melihat fungsi lainnya. Alangkah baiknya jika semua fungsi paralel memiliki perilaku yang konsisten dalam kasus ini.

Ini adalah duplikat dari #557.

Apakah async akhirnya melarang modifikasi array setelah fakta? Saya memiliki kasus penggunaan di mana akan menyenangkan untuk memodifikasi array asli setelah fakta, untuk beralih pada lebih banyak elemen daripada awalnya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat