Berikut adalah contoh yang dibuat-buat tentang apa yang terjadi: http://jsfiddle.net/adamjford/YNGcm/20/
HTML:
<a href="#">Click me!</a>
<div></div>
JavaScript:
function getSomeDeferredStuff() {
var deferreds = [];
var i = 1;
for (i = 1; i <= 10; i++) {
var count = i;
deferreds.push(
$.post('/echo/html/', {
html: "<p>Task #" + count + " complete.",
delay: count
}).success(function(data) {
$("div").append(data);
}));
}
return deferreds;
}
$(function() {
$("a").click(function() {
var deferreds = getSomeDeferredStuff();
$.when(deferreds).done(function() {
$("div").append("<p>All done!</p>");
});
});
});
Saya ingin "Semua selesai!" muncul setelah semua tugas yang ditangguhkan selesai, tetapi $.when()
tampaknya tidak tahu bagaimana menangani array objek yang Ditangguhkan. "Semua selesai!" terjadi pertama kali karena array bukan objek yang ditangguhkan, jadi jQuery berjalan di depan dan menganggap itu baru saja selesai.
Saya tahu orang bisa meneruskan objek ke fungsi seperti $.when(deferred1, deferred2, ..., deferredX)
tetapi tidak diketahui berapa banyak objek yang ditangguhkan akan ada di eksekusi dalam masalah aktual yang saya coba selesaikan.
javascript
jquery
argument-passing
jquery-deferred
.when
adamjford
sumber
sumber
$.when.apply
sama sekali untuk mendapatkan hasil yang sama.Jawaban:
Untuk meneruskan array nilai ke fungsi apa pun yang biasanya mengharapkannya sebagai parameter yang terpisah, gunakan
Function.prototype.apply
, jadi dalam hal ini Anda perlu:Lihat http://jsfiddle.net/YNGcm/21/
Di ES6, Anda bisa menggunakan
...
operator spread sebagai gantinya:Dalam kedua kasus tersebut, karena tidak mungkin Anda akan tahu sebelumnya berapa banyak parameter formal yang diperlukan
.then
pawang, pawang itu perlu memprosesarguments
array untuk mengambil hasil dari setiap janji.sumber
$.when
-f.apply(ctx, my_array)
akan memanggilf
denganthis == ctx
dan argumen diatur ke isi darimy_array
.$
vsnull
sebagai parameter pertama layak dibaca. Dalam kasus khusus ini, tidak masalah.$
kurang mengetik daripadanull
dan Anda aman saat$.when
implementasi berubah (bukan karena kemungkinan dalam kasus ini tetapi mengapa tidakthis
diubah secara default).Penanganan masalah di atas (terima kasih!) Tidak dengan benar mengatasi masalah mendapatkan kembali objek yang disediakan untuk metode yang ditangguhkan
resolve()
karena jQuery memanggildone()
dan memanggil kembalifail()
dengan parameter individual, bukan array. Itu berarti kita harus menggunakanarguments
pseudo-array untuk mendapatkan semua objek yang diselesaikan / ditolak dikembalikan oleh array yang ditangguhkan, yang jelek:Karena kami meneruskan dalam array yang ditangguhkan, alangkah baiknya untuk mendapatkan kembali array hasil. Akan lebih baik untuk mendapatkan kembali array aktual alih-alih pseudo-array sehingga kita dapat menggunakan metode seperti
Array.sort()
.Berikut ini adalah solusi terinspirasi oleh when.js 's
when.all()
metode yang alamat masalah ini:Sekarang Anda dapat dengan mudah memasukkan array dari ditangguhkan / janji dan mendapatkan kembali array objek yang diselesaikan / ditolak dalam panggilan balik Anda, seperti:
sumber
var toArray = function (args) { return deferreds.length > 1 ? $.makeArray(args) : [args]; }
sebagai gantiArray.prototype.slice.call
.Anda dapat menerapkan
when
metode ini ke array Anda:Bagaimana Anda bekerja dengan array jQuery Deferreds?
sumber
Saat memanggil beberapa panggilan AJAX paralel, Anda memiliki dua opsi untuk menangani masing-masing respons.
Promises'
larik dan$.when
yang menerimapromise
s dan panggilan.done
baliknya dipanggil ketika semuapromise
s berhasil dikembalikan dengan tanggapan masing-masing.Contoh
sumber
$.when
.for ... in
pada array ?!)(not recommended)
2.Tidak setuju -for ... in
ok karena array hanya berisi properti-properti yang perlu (tidak ada properti tambahan). thanx anywaysArray.prototype
. Dalam hal apa pun, untuk kode non-kinerja-kritis akan lebih baik digunakan.map
daripadafor
/push
loop, misalnyavar promises = capitalCities.map(ajaxRequest); $.when.apply($, promises).then(fillCountryCapitals)
- pekerjaan selesai.Sebagai alternatif sederhana, yang tidak memerlukan
$.when.apply
atauarray
, Anda dapat menggunakan pola berikut untuk menghasilkan janji tunggal untuk banyak janji paralel:misalnya
Catatan:
promise = promise.then(newpromise)
sumber
then()
panggilan dengan cara yang sama. Perilaku dengan$.when
adalah bertindak seperti itu paralel (tidak dirantai). Silakan coba sebelum membuang alternatif yang berguna karena tidak bekerja :)Saya ingin mengusulkan yang lain dengan menggunakan $ .each:
Kami dapat mendeklarasikan fungsi ajax seperti:
Bagian dari kode tempat kami membuat berbagai fungsi dengan ajax untuk dikirim:
Dan memanggil fungsi dengan mengirim ajax:
sumber
Jika Anda mentransisikan dan memiliki akses ke ES6, Anda dapat menggunakan sintaksis spread yang secara khusus menerapkan setiap item yang dapat diulang dari suatu objek sebagai argumen diskrit, seperti yang
$.when()
dibutuhkannya.MDN Link - Sebarkan Sintaks
sumber
Jika Anda menggunakan angularJS atau varian pustaka janji Q, maka Anda memiliki
.all()
metode yang memecahkan masalah ini.lihat API lengkap:
https://github.com/kriskowal/q/wiki/API-Reference#promiseall
https://docs.angularjs.org/api/ng/service/$q
sumber
.map
sini tapi oh well).Saya memiliki kasus yang sangat mirip di mana saya memposting di setiap loop dan kemudian mengatur markup html di beberapa bidang dari nomor yang diterima dari ajax. Saya kemudian perlu melakukan penjumlahan dari nilai-nilai (sekarang diperbarui) dari bidang-bidang ini dan tempatkan di bidang total.
Jadi masalahnya adalah saya mencoba melakukan penjumlahan pada semua nomor tetapi belum ada data yang kembali dari panggilan ajax async. Saya perlu menyelesaikan fungsi ini dalam beberapa fungsi untuk dapat menggunakan kembali kode. Fungsi luar saya menunggu data sebelum saya pergi dan melakukan beberapa hal dengan DOM yang sepenuhnya diperbarui.
sumber