Bagaimana cara membuat loop dengan benar untuk memastikan panggilan janji berikut dan logger.log (res) yang dirantai berjalan secara sinkron melalui iterasi? (burung biru)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Saya mencoba cara berikut (metode dari http://blog.victorquinn.com/javascript-promise- While-loop )
var Promise = require('bluebird');
var promiseWhile = function(condition, action) {
var resolver = Promise.defer();
var loop = function() {
if (!condition()) return resolver.resolve();
return Promise.cast(action())
.then(loop)
.catch(resolver.reject);
};
process.nextTick(loop);
return resolver.promise;
});
var count = 0;
promiseWhile(function() {
return count < 10;
}, function() {
return new Promise(function(resolve, reject) {
db.getUser(email)
.then(function(res) {
logger.log(res);
count++;
resolve();
});
});
}).then(function() {
console.log('all done');
});
Meskipun tampaknya berhasil, tetapi menurut saya ini tidak menjamin urutan pemanggilan logger.log (res);
Ada saran?
javascript
node.js
promise
bluebird
pengguna2127480
sumber
sumber
loop
fungsi tersebut adalah cara untuk melakukan loop sinkron). Menurut Anda, mengapa tidak ada jaminan?while
kerja kode itu?Jawaban:
Sebenarnya, memang begitu. Pernyataan itu dijalankan sebelum
resolve
panggilan.Banyak. Yang paling penting adalah penggunaan antipattern buat-janji-manual - lakukan saja
Kedua,
while
fungsi itu bisa banyak disederhanakan:Ketiga, saya tidak akan menggunakan
while
loop (dengan variabel penutupan) tetapifor
loop:sumber
action
mengambilvalue
sebagai argumen dalampromiseFor
. JADI tidak akan membiarkan saya melakukan pengeditan sekecil itu. Terima kasih, ini sangat membantu dan elegan.while
loop menguji beberapa status global sementara sebuahfor
loop memiliki variabel iterasinya (penghitung) yang terikat ke badan loop itu sendiri. Sebenarnya saya telah menggunakan pendekatan yang lebih fungsional yang terlihat lebih seperti iterasi fixpoint daripada loop. Periksa kembali kode mereka,value
parameternya berbeda..bind()
mengaburkan yang baruvalue
, saya pikir saya mungkin memilih untuk menggunakan fungsi tersebut agar mudah dibaca. Dan maaf jika saya terlalu tebal tetapi jikapromiseFor
danpromiseWhile
tidak hidup berdampingan, lalu bagaimana yang satu memanggil yang lain?return …
olehreturn Promise.resolve(…)
. Jika Anda membutuhkan perlindungan tambahan terhadapcondition
atauaction
melempar pengecualian (sepertiPromise.method
menyediakannya ), bungkus seluruh badan fungsi dalam areturn Promise.resolve().then(() => { … })
Promise.resolve().then(action).…
atauPromise.resolve(action()).…
, Anda tidak perlu membungkus nilai pengembalianthen
Jika Anda benar-benar menginginkan seorang jenderal
promiseWhen()
fungsi untuk ini dan tujuan lainnya, maka lakukanlah dengan menggunakan penyederhanaan Bergi. Namun, karena cara promise berfungsi, meneruskan callback dengan cara ini umumnya tidak diperlukan dan memaksa Anda untuk melewati rintangan kecil yang rumit.Sejauh yang saya tahu Anda sedang mencoba:
.then()
rantai melalui rekursi.Didefinisikan demikian, masalahnya sebenarnya adalah yang dibahas dalam "The Collection Kerfuffle" di Promise Anti-patterns , yang menawarkan dua solusi sederhana:
Array.prototype.map()
Array.prototype.reduce()
.Pendekatan paralel akan (secara langsung) memberikan masalah yang Anda coba hindari - bahwa urutan tanggapan tidak pasti. Pendekatan serial akan membangun
.then()
rantai yang diperlukan - datar - tanpa rekursi.Hubungi sebagai berikut:
Seperti yang Anda lihat, tidak perlu var luar yang jelek
count
ataucondition
fungsi terkaitnya . Batas (dari 10 dalam pertanyaan) ditentukan seluruhnya oleh panjang larikarrayOfEmailAddys
.sumber
Inilah cara saya melakukannya dengan objek Janji standar.
sumber
chain = chain.then(func.bind(null, "...your params here"));
atauchain = chain.then(() => func("your params here"));
Diberikan
Yg dibutuhkan
Larutan
sumber
async
akan menjadi kata yang dicadangkan dalam JavaScript, mungkin menambahkan kejelasan untuk mengganti nama fungsi itu di sini.current
tidak digunakan.Ada cara baru untuk menyelesaikan ini dan itu dengan menggunakan async / await.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await
sumber
Fungsi yang disarankan Bergi sangat bagus:
Saya tetap ingin menambahkan sedikit, yang masuk akal, saat menggunakan promise:
Dengan cara ini while loop bisa disematkan ke dalam rantai janji dan diselesaikan dengan lastValue (juga jika action () tidak pernah dijalankan). Lihat contoh:
sumber
Saya akan membuat sesuatu seperti ini:
dengan cara ini, dataAll adalah larik terurut dari semua elemen untuk dicatat. Dan operasi log akan dilakukan ketika semua janji sudah selesai.
sumber
Gunakan async dan await (es6):
sumber
sumber
Bagaimana kalau yang ini menggunakan BlueBird ?
sumber
Berikut metode lain (ES6 w / std Promise). Menggunakan kriteria keluar tipe lodash / garis bawah (return === false). Perhatikan bahwa Anda dapat dengan mudah menambahkan metode exitIf () dalam opsi untuk dijalankan di doOne ().
sumber
Menggunakan objek janji standar, dan membuat janji mengembalikan hasilnya.
sumber
Pertama, ambil array promise (promise array) dan setelah selesaikan array promise ini menggunakan
Promise.all(promisearray)
.sumber