Saya memiliki berbagai Janji yang saya selesaikan Promise.all(arrayOfPromises);
Saya melanjutkan untuk melanjutkan rantai janji. Terlihat seperti ini
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler();
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Saya ingin menambahkan pernyataan tangkap untuk menangani janji individu jika terjadi kesalahan, tetapi ketika saya mencoba, Promise.all
mengembalikan kesalahan pertama yang ditemukan (mengabaikan sisanya), dan kemudian saya tidak bisa mendapatkan data dari sisa janji di array (itu tidak salah).
Saya sudah mencoba melakukan sesuatu seperti ..
existingPromiseChain = existingPromiseChain.then(function() {
var arrayOfPromises = state.routes.map(function(route){
return route.handler.promiseHandler()
.then(function(data) {
return data;
})
.catch(function(err) {
return err
});
});
return Promise.all(arrayOfPromises)
});
existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
// do stuff with my array of resolved promises, eventually ending with a res.send();
});
Tetapi itu tidak menyelesaikan.
Terima kasih!
-
Edit:
Apa jawaban di bawah ini sepenuhnya benar, kode itu rusak karena alasan lain. Jika ada yang tertarik, ini adalah solusi yang saya akhirnya ...
Rantai Server Node Express
serverSidePromiseChain
.then(function(AppRouter) {
var arrayOfPromises = state.routes.map(function(route) {
return route.async();
});
Promise.all(arrayOfPromises)
.catch(function(err) {
// log that I have an error, return the entire array;
console.log('A promise failed to resolve', err);
return arrayOfPromises;
})
.then(function(arrayOfPromises) {
// full array of resolved promises;
})
};
Panggilan API (panggilan route.async)
return async()
.then(function(result) {
// dispatch a success
return result;
})
.catch(function(err) {
// dispatch a failure and throw error
throw err;
});
Menempatkan .catch
untuk Promise.all
sebelum .then
tampaknya telah melayani tujuan menangkap kesalahan dari janji asli, tetapi kemudian mengembalikan seluruh array ke yang berikutnya.then
Terima kasih!
.then(function(data) { return data; })
dapat sepenuhnya dihapusthen
ataucatch
penangan dan ada kesalahan yang terjadi. Omong-omong, apakah simpul ini?Jawaban:
Promise.all
semua atau tidak sama sekali. Itu menyelesaikan setelah semua janji dalam array menyelesaikan, atau menolak segera setelah salah satu dari mereka menolak. Dengan kata lain, itu bisa diselesaikan dengan array dari semua nilai yang diselesaikan, atau ditolak dengan satu kesalahan.Beberapa perpustakaan memiliki sesuatu yang disebut
Promise.when
, yang saya pahami sebagai gantinya akan menunggu semua janji dalam array untuk menyelesaikan atau menolak, tapi saya tidak terbiasa dengan itu, dan itu tidak di ES6.Kode Anda
Saya setuju dengan orang lain di sini bahwa perbaikan Anda harus bekerja. Itu harus diselesaikan dengan array yang mungkin berisi campuran dari nilai yang berhasil dan objek kesalahan. Itu tidak biasa untuk melewatkan objek kesalahan di jalur sukses tetapi dengan asumsi kode Anda mengharapkan mereka, saya tidak melihat masalah dengan itu.
Satu-satunya alasan saya bisa memikirkan mengapa itu "tidak menyelesaikan" adalah karena kode gagal Anda tidak menunjukkan kepada kami dan alasan Anda tidak melihat pesan kesalahan tentang ini adalah karena rantai janji ini tidak diakhiri dengan final catch (sejauh apa yang Anda tunjukkan pada kami).
Saya telah mengambil kebebasan untuk memfaktorkan "rantai yang ada" dari contoh Anda dan mengakhiri rantai dengan tangkapan. Ini mungkin tidak tepat untuk Anda, tetapi bagi orang yang membaca ini, penting untuk selalu mengembalikan atau menghentikan rantai, atau potensi kesalahan, bahkan kesalahan pengodean, akan disembunyikan (yang saya duga terjadi di sini):
sumber
Promise.allSettled()
dengan dukungan yang layak. Lihat referensi .Promise.all
gagal, saat utas pertama gagal. Namun sayangnya semua utas lainnya masih terus berjalan sampai selesai. Tidak ada yang dibatalkan, bahkan lebih buruk: Tidak ada cara untuk membatalkan utasPromise
. Jadi, apa pun yang dilakukan thread (dan memanipulasi) mereka melanjutkan, mereka mengubah status dan variabel, mereka menggunakan CPU, tetapi pada akhirnya mereka tidak mengembalikan hasilnya. Anda perlu menyadari hal ini untuk tidak menghasilkan kekacauan, misalnya ketika Anda mengulangi / coba lagi panggilan.JAWABAN BARU
API Janji MASA DEPAN
sumber
e
tidak harus menjadi seorangError
. Ini bisa berupa string, misalnya, jika seseorang mengembalikannya sepertiPromise.reject('Service not available')
..then()
dan.catch()
.Promise.resolve()
akan memberikan nilai ke yang pertama, sedangkanPromise.reject()
akan memberikannya ke yang kedua. Anda dapat membungkus mereka dalam objek misalnya:p.then(v => ({success: true, value: v})).catch(e => ({success: false, error: e}))
.Untuk melanjutkan
Promise.all
loop (bahkan ketika Janji menolak) saya menulis fungsi utilitas yang disebutexecuteAllPromises
. Fungsi utilitas ini mengembalikan objek denganresults
danerrors
.Idenya adalah bahwa semua Janji yang Anda lewati
executeAllPromises
akan dibungkus menjadi Janji baru yang akan selalu diselesaikan. Janji baru diselesaikan dengan array yang memiliki 2 tempat. Spot pertama memiliki nilai penyelesaian (jika ada) dan spot kedua menyimpan kesalahan (jika Janji yang dibungkus menolak).Sebagai langkah terakhir,
executeAllPromises
akumulasi semua nilai janji yang dibungkus dan mengembalikan objek akhir dengan array untukresults
dan array untukerrors
.Ini kodenya:
sumber
ES2020 memperkenalkan metode baru untuk tipe Janji:
Promise.allSettled()
Promise.allSettled memberi Anda sinyal ketika semua janji input diselesaikan, yang berarti mereka dipenuhi atau ditolak. Ini berguna dalam kasus di mana Anda tidak peduli dengan keadaan janji, Anda hanya ingin tahu kapan pekerjaan itu dilakukan, terlepas dari apakah itu berhasil.
Baca lebih lanjut di posting blog v8 https://v8.dev/features/promise-combinators
sumber
Seperti yang dikatakan @jib,
Meskipun demikian, Anda dapat mengontrol janji-janji tertentu yang "diizinkan" untuk gagal dan kami ingin melanjutkannya
.then
.Sebagai contoh.
sumber
jika Anda bisa menggunakan perpustakaan q https://github.com/kriskowal/q ia memiliki metode q.allSettled () yang dapat menyelesaikan masalah ini, Anda dapat menangani setiap janji tergantung pada negaranya apakah terpenuhi atau ditolak sehingga
sumber
q
), akan lebih bermanfaat jika Anda memberikan contoh penggunaan yang terkait dengan pertanyaan. Seperti berdiri, jawaban Anda tidak menjelaskan bagaimana perpustakaan ini dapat membantu menyelesaikan masalah.Menggunakan Async, tunggu -
di sini satu fungsi async func1 mengembalikan nilai yang diselesaikan, dan func2 melempar kesalahan dan mengembalikan nol dalam situasi ini, kita bisa menanganinya seperti yang kita inginkan dan mengembalikan sesuai.
Output adalah - ['func1', null]
sumber
Bagi mereka yang menggunakan ES8 yang tersandung di sini, Anda dapat melakukan sesuatu seperti berikut, menggunakan fungsi async :
sumber
Kami dapat menangani penolakan di tingkat janji individual, jadi ketika kami mendapatkan hasil di larik hasil kami, indeks larik yang telah ditolak akan menjadi
undefined
. Kami dapat menangani situasi itu sesuai kebutuhan, dan menggunakan hasil yang tersisa.Di sini saya telah menolak janji pertama, jadi janji itu tidak ditentukan, tetapi kita bisa menggunakan hasil dari janji kedua, yaitu pada indeks 1.
sumber
Sudahkah Anda mempertimbangkan
Promise.prototype.finally()
?Tampaknya dirancang untuk melakukan persis apa yang Anda inginkan - menjalankan fungsi setelah semua janji telah diselesaikan (diselesaikan / ditolak), terlepas dari beberapa janji yang ditolak.
Dari dokumentasi MDN :
Itu
finally()
Metode dapat berguna jika Anda ingin melakukan beberapa pengolahan atau pembersihan setelah janji tersebut diselesaikan, terlepas dari hasilnya.The
finally()
Metode ini sangat mirip dengan memanggil.then(onFinally, onFinally)
namun ada beberapa perbedaan:Saat membuat fungsi inline, Anda bisa melewatkannya sekali, alih-alih dipaksa untuk mendeklarasikannya dua kali, atau membuat variabel untuknya.
Akhirnya panggilan balik tidak akan menerima argumen apa pun, karena tidak ada cara yang dapat diandalkan untuk menentukan apakah janji itu dipenuhi atau ditolak. Kasus penggunaan ini tepat ketika Anda tidak peduli tentang alasan penolakan, atau nilai pemenuhan, dan karenanya tidak perlu menyediakannya.
Tidak seperti
Promise.resolve(2).then(() => {}, () => {})
(yang akan diselesaikan dengan undefined),Promise.resolve(2).finally(() => {})
akan diselesaikan dengan 2. Demikian pula, tidak sepertiPromise.reject(3).then(() => {}, () => {})
(yang akan dipenuhi dengan undefined),Promise.reject(3).finally(() => {})
akan ditolak dengan 3.== Fallback ==
Jika versi JavaScript Anda tidak mendukung,
Promise.prototype.finally()
Anda dapat menggunakan solusi ini dari Jake Archibald :Promise.all(promises.map(p => p.catch(() => undefined)));
sumber
Promises.allSettled()
benar-benar dilaksanakan (didokumentasikan oleh MDN di sini ), makaPromises.all.finally()
tampaknya akan mencapai hal yang sama. Saya akan mencobanya ...allSettled()
.allSettled()
belum diterapkan di mana pun (belum), jadi saya tidak ingin maju dari kenyataan. Saya sukses dengan ituPromises.all(myPromiseArray).finally()
, dan itu cocok dengan jawaban ini. SetelahallSettled()
benar-benar ada, maka saya dapat mengujinya dan mencari tahu cara kerjanya. Sampai saat itu, siapa yang tahu apa yang sebenarnya akan diterapkan browser? Kecuali jika Anda memiliki info terbaru yang bertentangan ...Promise.allSettled
tidak diterapkan di Firefox, tetapi tampaknya ada di Chrome. Hanya karena dokumen mengatakan itu diterapkan bukan berarti itu benar-benar diterapkan. Saya tidak akan menggunakannya dalam waktu dekat.Bergantian, jika Anda memiliki kasus di mana Anda tidak terlalu peduli tentang nilai-nilai janji yang diselesaikan ketika ada satu kegagalan tetapi Anda masih ingin mereka berjalan, Anda bisa melakukan sesuatu seperti ini yang akan diselesaikan dengan janji-janji seperti biasa ketika mereka semua berhasil dan menolak dengan janji-janji yang gagal ketika salah satu dari mereka gagal:
sumber
Anda selalu dapat membungkus janji Anda mengembalikan fungsi dengan cara mereka menangkap kegagalan dan mengembalikan bukan nilai yang disepakati (misalnya error.message), sehingga pengecualian tidak akan menggulung sampai ke fungsi Promise.all dan menonaktifkannya.
sumber
Saya telah menemukan cara (penyelesaian) untuk melakukan ini tanpa membuatnya disinkronkan.
Jadi seperti yang disebutkan sebelumnya
Promise.all
tidak ada sama sekali.jadi ... Gunakan janji terlampir untuk menangkap dan memaksakan tekad.
sumber
Anda perlu tahu cara mengidentifikasi kesalahan dalam hasil Anda. Jika Anda tidak memiliki kesalahan standar yang diharapkan, saya sarankan Anda menjalankan transformasi pada setiap kesalahan di blok tangkap yang membuatnya dapat diidentifikasi dalam hasil Anda.
sumber
Bukan cara terbaik untuk membuat kesalahan log, tetapi Anda selalu dapat mengatur semuanya ke array untuk janji, dan menyimpan hasil yang dihasilkan ke dalam variabel baru.
Jika Anda menggunakan graphQL, Anda perlu memposting proses tanggapan terlepas dan jika tidak menemukan referensi yang benar itu akan merusak aplikasi, mempersempit di mana masalahnya berada
sumber
Begitulah cara
Promise.all
dirancang untuk bekerja. Jika satu janjireject()
, seluruh metode segera gagal.Ada kasus penggunaan di mana seseorang mungkin ingin memiliki
Promise.all
memungkinkan untuk janji gagal. Untuk mewujudkannya, jangan gunakanreject()
pernyataan apa pun dalam janji Anda. Namun, untuk memastikan aplikasi / skrip Anda tidak membeku seandainya ada janji tunggal yang mendasari tidak pernah mendapat tanggapan, Anda perlu memberi batas waktu padanya.sumber
reject()
dalam janji Anda baik-baik saja, tetapi bagaimana jika Anda perlu menggunakan janji perpustakaan lain?Saya menulis perpustakaan npm untuk mengatasi masalah ini lebih indah. https://github.com/wenshin/promiseallend
Install
2017-02-25 api baru, itu tidak melanggar prinsip janji
———————————————————————————————
Api buruk tua, jangan gunakan itu!
sumber
Promise.all
. Tapi itu akan mengumpulkan semua data dan kesalahan dari setiap janji. juga mendukung input objek, bukan itu intinya. setelah mengumpulkan semua data dan kesalahan, saya menggantipromise.then
metode untuk menangani callback terdaftar yang termasuk ditolak dan dipenuhi. Untuk detail Anda dapat melihat kodeonFulfilled
danonRejected
penangan yang diteruskan kethen
?fulfilled
danrejected
. Tapi itu benar-benar menyebabkan masalah sulit untuk kompatibel dengan semua kasus penggunaan janji secara normal, sepertionFulfilled
danonRejected
semua kembaliPromise.reject()
atauPromise.resolve()
. Sejauh ini saya tidak jelas bagaimana menyelesaikannya, apakah ada yang punya ide yang lebih baik? Jawaban terbaik untuk saat ini memiliki masalah adalah, mungkin tidak dapat menyaring data dan kesalahan di lingkungan browser.