use*_*480 113 javascript node.js promise bluebird
如何正确构造一个循环以确保后续的promise调用和链式logger.log(res)通过迭代同步运行?(蓝鸟)
db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法(来自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');
});
Run Code Online (Sandbox Code Playgroud)
虽然它似乎工作,但我不认为它保证调用logger.log(res)的顺序;
有什么建议?
Roa*_*888 132
如果你真的想要promiseWhen()这个和其他目的的一般功能,那么一定要这样做,使用Bergi的简化.但是,由于promises的工作方式,以这种方式传递回调通常是不必要的,并迫使你跳过复杂的小箍.
据我所知,你正在尝试:
.then()通过递归建立链来实现这一目的.因此,问题实际上是Promise Anti-patterns中 "The Collection Kerfuffle"中讨论的问题,它提供了两个简单的解决方案:
Array.prototype.map() Array.prototype.reduce().并行方法将(直接)给出您试图避免的问题 - 响应的顺序是不确定的.串行方法将构建所需的.then()链 - 平 - 没有递归.
function fetchUserDetails(arr) {
return arr.reduce(function(promise, email) {
return promise.then(function() {
return db.getUser(email).done(function(res) {
logger.log(res);
});
});
}, Promise.resolve());
}
Run Code Online (Sandbox Code Playgroud)
请致电如下:
//Compose here, by whatever means, an array of email addresses.
var arrayOfEmailAddys = [...];
fetchUserDetails(arrayOfEmailAddys).then(function() {
console.log('all done');
});
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,不需要丑陋的外部变量count或它的相关condition功能.限制(问题中的10)完全由数组的长度决定arrayOfEmailAddys.
Ber*_*rgi 78
我不认为它保证调用logger.log(res)的顺序;
实际上,确实如此.该声明在resolve通话之前执行.
有什么建议?
许多.最重要的是你使用create-promise-manual反模式 - 只做
promiseWhile(…, function() {
return db.getUser(email)
.then(function(res) {
logger.log(res);
count++;
});
})…
Run Code Online (Sandbox Code Playgroud)
其次,这个while功能可以简化很多:
var promiseWhile = Promise.method(function(condition, action) {
if (!condition()) return;
return action().then(promiseWhile.bind(null, condition, action));
});
Run Code Online (Sandbox Code Playgroud)
第三,我不会使用while循环(带闭包变量)而是for循环:
var promiseFor = Promise.method(function(condition, action, value) {
if (!condition(value)) return value;
return action(value).then(promiseFor.bind(null, condition, action));
});
promiseFor(function(count) {
return count < 10;
}, function(count) {
return db.getUser(email)
.then(function(res) {
logger.log(res);
return ++count;
});
}, 0).then(console.log.bind(console, 'all done'));
Run Code Online (Sandbox Code Playgroud)
you*_*rth 37
以下是我使用标准Promise对象的方法.
// Given async function sayHi
function sayHi() {
return new Promise((resolve) => {
setTimeout(() => {
console.log('Hi');
resolve();
}, 3000);
});
}
// And an array of async functions to loop through
const asyncArray = [sayHi, sayHi, sayHi];
// We create the start of a promise chain
let chain = Promise.resolve();
// And append each function in the array to the promise chain
for (const func of asyncArray) {
chain = chain.then(func);
}
// Output:
// Hi
// Hi (After 3 seconds)
// Hi (After 3 more seconds)
Run Code Online (Sandbox Code Playgroud)
小智 9
特定
需要
解
let asyncFn = (item) => {
return new Promise((resolve, reject) => {
setTimeout( () => {console.log(item); resolve(true)}, 1000 )
})
}
// asyncFn('a')
// .then(()=>{return async('b')})
// .then(()=>{return async('c')})
// .then(()=>{return async('d')})
let a = ['a','b','c','d']
a.reduce((previous, current, index, array) => {
return previous // initiates the promise chain
.then(()=>{return asyncFn(array[index])}) //adds .then() promise for each item
}, Promise.resolve())
Run Code Online (Sandbox Code Playgroud)
小智 5
有一种新方法可以解决这个问题,那就是使用 async/await。
async function myFunction() {
while(/* my condition */) {
const res = await db.getUser(email);
logger.log(res);
}
}
myFunction().then(() => {
/* do other stuff */
})
Run Code Online (Sandbox Code Playgroud)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://ponyfoo.com/articles/understanding-javascript-async-await