Janji. Semua gelisah


Pada pertemuan ke 71 dari Ecma TC39, proyek dan implementasi referensi dari Promise.allSettled . Promise.allSettled , yang ketiga dari empat kombinator utama dari janji, akan dipertimbangkan.


Penulis : Jason Williams (BBC), Robert Pumley (Bloomberg), Matthias Binens (Google)
Juara : Matthias Binens (Google)
Tahap : 3


Untuk penggemar podcast, digandakan di YouTube .


Pengantar dan Motivasi


Ada empat kombinator utama di dunia janji:


  • Promise.all . ES2015. Penutupan pada janji ditolak / ditolak pertama.
  • Promise.race . ES2015. Menutup pada janji pertama entah bagaimana diselesaikan / diselesaikan.
  • Promise.any . Tahap 1. Menutup pada janji puas / terpenuhi pertama.
  • Promise.allSettled . Semua Promise.allSettled . Tahap 3 → Tahap 4. Tidak menutup.

Semuanya diwakili secara luas di perpustakaan pengguna biasa, masing-masing berguna dalam dirinya sendiri dan cocok dalam berbagai situasi.


Aplikasi utama dari kombinator ini terjadi ketika Anda ingin melakukan suatu tindakan segera setelah menyelesaikan banyak permintaan, terlepas dari apakah itu berakhir dengan sukses atau gagal. Sisa dari kombinator janji tertutup ( korsleting ), membuang hasil nilai input yang telah kehilangan balapan untuk keadaan sistem tertentu. Promise.allSettled unik karena selalu mengharapkan semua orang yang bertanggung jawab.


Promise.allSettled mengembalikan sebuah janji, yang dieksekusi dengan mengembalikan sejumlah snapshot dari negara-negara janji, tetapi hanya setelah benar-benar semua janji awal diselesaikan.


Dari mana nama allSettled berasal?


Kami mengatakan bahwa janji telah diselesaikan ( diselesaikan ) jika tidak ditangguhkan ditangguhkan , mis. ketika dia puas atau ditolak - salah satu dari dua hal. Untuk memahami terminologi, lihat dokumen States and Fates yang lama .


Dan juga, nama ini, allSettled , banyak digunakan di perpustakaan yang ada yang menerapkan fungsi ini. Daftarnya akan di bawah.


Contohnya


Bayangkan Anda perlu beralih pada array janji dan mengembalikan nilai baru dengan status yang diketahui (yang terjadi di salah satu dari dua cabang logika yang mungkin).


 function reflect(promise) { return promise.then( (v) => { return { status: 'fulfilled', value: v }; }, (error) => { return { status: 'rejected', reason: error }; } ); } const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.all(promises.map(reflect)); const successfulPromises = results.filter(p => p.status === 'fulfilled'); 

API yang diusulkan memungkinkan pengembang untuk memproses opsi-opsi ini, tanpa perlu membuat fungsi reflect secara mandiri, atau menyimpan hasilnya dalam variabel sementara. API baru terlihat seperti ini:


 const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const successfulPromises = results.filter(p => p.status === 'fulfilled'); 

Jika karena alasan tertentu kita perlu menolak janji, maka mungkin kita perlu mengumpulkan alasan atas apa yang terjadi. allSettled membuat ini semudah ini.


 const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ]; const results = await Promise.allSettled(promises); const errors = results .filter(p => p.status === 'rejected') .map(p => p.reason); 

Contoh nyata


Cukup umum adalah keinginan untuk mengetahui bahwa semua permintaan telah selesai, terlepas dari status masing-masing. Ini penting ketika Anda ingin melakukan perbaikan bertahap di masa depan. Kami tidak selalu perlu mendapatkan respons dari API.


 const urls = [ /* ... */ ]; const requests = urls.map(x => fetch(x)); // , -    ,  - - . //        ,   . try { await Promise.all(requests); console.log('  ,    .'); } catch { console.log('-    ,     . .'); } 

Menggunakan Promise.allSettled Anda dapat menulis sesuatu yang lebih sesuai dengan harapan kami.


 //   ,     API  . Promise.allSettled(requests).finally(() => { console.log('  :    ,   '); removeLoadingIndicator(); }); 

Implementasi khusus



Dalam bahasa lain


Fungsionalitas serupa ada dalam bahasa lain, dengan nama yang berbeda. Karena tidak ada mekanisme universal yang langsung kompatibel dengan banyak bahasa, dokumen ini mengikuti contoh nama-nama dari perpustakaan yang tercantum di atas. Begini tampilannya dalam bahasa lain:


  • Rust - futures::join ;
  • C # - Task.WhenAll . Task.WhenAll . Anda dapat menggunakan try / catch atau TaskContinuationOptions.OnlyOnFaulted ;
  • Python - asyncio.wait dengan opsi ALL_COMPLETED
  • Java - CompletableFuture.allOf

Bahan untuk studi lebih lanjut



Notulen rapat TC39



Spesifikasi



Implementasi


Source: https://habr.com/ru/post/id459970/


All Articles