Lebih
Sementara loop dengan janji-janji
Apa yang akan menjadi idiomatic cara untuk melakukan sesuatu seperti while loop dengan janji-janji. Jadi:
melakukan sesuatu jika kondisi masih berdiri melakukannya lagi ulangi kemudian melakukan sesuatu yang lain.
dosomething.then(possilblydomoresomethings).then(finish)
I've dilakukan dengan cara ini aku bertanya-tanya jika ada yang lebih baik/lebih idomatic cara?
var q = require('q');
var index = 1;
var useless = function(){
var currentIndex = index;
console.log(currentIndex)
var deferred = q.defer();
setTimeout(function(){
if(currentIndex > 10)
deferred.resolve(false);
else deferred.resolve(true);
},500);
return deferred.promise;
}
var control = function(cont){
var deferred = q.defer();
if(cont){
index = index + 1;
useless().then(control).then(function(){
deferred.resolve();
});
}
else deferred.resolve();
return deferred.promise;
}
var chain = useless().then(control).then(function(){console.log('done')});
Output: Satu Dua Tiga Empat Lima Enam Tujuh Delapan Sembilan Sepuluh Sebelas dilakukan
69
13
Berikut ini's sebuah fungsi yang dapat digunakan kembali yang saya pikir cukup jelas.
Ini adalah cara paling sederhana I've ditemukan untuk mengekspresikan pola dasar: anda mendefinisikan sebuah fungsi yang memanggil janji, cek hasilnya, dan kemudian menyebut dirinya lagi atau berakhir.
Melihatnya dalam tindakan di JSBin
Jika anda menggunakan sebuah janji yang menyelesaikan atau menolak, anda akan mendefinisikan
maka
danmenangkap
bukan menggunakan if-clause.Jika anda memiliki sebuah array dari janji-janji, anda hanya akan mengubah
loop
untuk menggeser atau pop berikutnya setiap waktu.EDIT: Berikut's versi yang menggunakan
async/menanti
, karena itu's 2018:Melihatnya dalam tindakan di CodePen
Seperti yang anda lihat, menggunakan normal while loop dan tidak ada rekursi.
I'a menggunakan sebuah objek untuk membungkus nilai. Dengan cara itu anda dapat memiliki
dilakukan
properti untuk membiarkan loop tahu anda'kembali dilakukan.Ini adalah untuk bluebird tidak q tapi karena anda tidak't menyebutkan q khusus.. di bluebird api doc penulis menyebutkan kembali janji-fungsi pembangkit akan lebih idiomatik dari menggunakan deferreds.
Karena saya dapat't mengomentari Stuart K's jawaban saya'll menambahkan sedikit di sini. Berdasarkan Stuart K's jawaban anda dapat merebusnya untuk anehnya konsep sederhana: menggunakan Kembali janji yang belum terpenuhi. Apa yang telah ia pada dasarnya adalah:
Stuart's jawaban untuk yang lebih generik solusi, tapi dasar-dasar yang mengagumkan (setelah anda menyadari bagaimana cara kerjanya).
Pola ini sekarang lebih mudah disebut dengan menggunakan q-flow. Contoh, untuk masalah di atas:
Berikut ini adalah sebuah ekstensi untuk
Janji
prototipe untuk meniru perilakuuntuk
loop. Mendukung janji-janji atau langsung nilai-nilai untuk inisialisasi, kondisi, loop tubuh, dan peningkatan bagian-bagian. Ini juga memiliki dukungan penuh untuk pengecualian, dan ia tidak memiliki kebocoran memori. Sebuah contoh diberikan di bawah ini tentang cara menggunakannya.Saya sekarang menggunakan ini:
Ini menerima sebuah array
arr
dan fungsibekerja
dan kembaliJanji
. Disediakan fungsi dipanggil sekali untuk masing-masing elemen dalam array dan akan diteruskan elemen saat ini dan itu's indeks dalam array. Mungkin sinkron atau asinkron, yang dalam hal ini harus kembali Janji.Anda dapat menggunakannya seperti ini:
Setiap item dalam array akan ditangani pada gilirannya. Setelah semua ditangani, kode yang diberikan untuk
.maka()
akan berjalan, atau, jika beberapa kesalahan yang terjadi, kode yang diberikan untuk.menangkap()
. Dalambekerja
fungsi, anda dapatmembuang
sebuahKesalahan
(dalam kasus sinkron fungsi) ataumenolak
yangMenjanjikan
(dalam kasus async fungsi) untuk membatalkan loop.Banyak jawaban di sini dan apa yang anda mencoba untuk mencapai sangat tidak praktis. tapi ini harus bekerja. Ini dilaksanakan di sebuah aws lambda function, dengan Node.js 10 ia akan pergi sampai fungsi timeout. Hal ini juga dapat mengkonsumsi jumlah yang layak dari memori.
Diuji pada lambda dan berjalan baik-baik saja selama lebih dari 5 menit. Tapi seperti yang dinyatakan oleh orang lain ini bukan hal yang baik untuk dilakukan.
Menggunakan ES6 Janji, saya datang dengan ini. Itu rantai janji-janji dan kembali janji. It's tidak secara teknis sebuah while loop, tetapi tidak menunjukkan bagaimana untuk iterate atas janji-janji serentak.
[Di sini's my biola.][1]
Saya pikir saya mungkin juga melemparkan topi ke dalam ring, dengan menggunakan ES6 janji-Janji...
Sang
eksekutor
argumen adalah yang sama sebagai yang berlalu untuk sebuahJanji
konstruktor, tapi akan dipanggil berulang-ulang sampai memicu keberhasilan callback. Thebefore_retry
fungsi memungkinkan untuk custom penanganan kesalahan pada gagal mencoba. Jika ia mengembalikan truthy nilai itu akan dianggap sebagai bentuk keberhasilan dan "loop" akan berakhir, dengan truthy sebagai hasilnya. Jika tidak adabefore_retry
fungsi terdaftar, atau mengembalikan falsey nilai, maka loop akan dijalankan selama iterasi. Pilihan ketiga adalah bahwabefore_retry
fungsi melempar kesalahan itu sendiri. Jika ini terjadi, maka "loop" akan berakhir, melewati kesalahan-kesalahan itu sebagai sebuah kesalahan.Berikut ini adalah contoh:
Output untuk pilihan 0:
Output untuk opsi 1:
Output untuk opsi 2:
Saya menulis sebuah modul yang membantu anda melakukan dirantai loop dari asynchronous tugas dengan janji-janji, hal ini didasarkan pada jawaban di atas disediakan oleh juandopazo
https://github.com/CascadeEnergy/promise-seedloop