Gru*_*mle 69 loops node.js promise q
什么是惯用的方式做一些像承诺的while循环.所以:
如果条件仍然有效,请再做一次然后再做其他事情.
dosomething.then(possilblydomoresomethings).then(finish)
Run Code Online (Sandbox Code Playgroud)
我是这样做的,我想知道是否有更好/更多的自我方式?
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')});
Run Code Online (Sandbox Code Playgroud)
输出:1 2 3 4 5 6 7 8 9 10 11完成
Stu*_*t K 58
这是一个可重用的功能,我认为非常清楚.
var Q = require("q");
// `condition` is a function that returns a boolean
// `body` is a function that returns a promise
// returns a promise for the completion of the loop
function promiseWhile(condition, body) {
var done = Q.defer();
function loop() {
// When the result of calling `condition` is no longer true, we are
// done.
if (!condition()) return done.resolve();
// Use `when`, in case `body` does not return a promise.
// When it completes loop again otherwise, if it fails, reject the
// done promise
Q.when(body(), loop, done.reject);
}
// Start running the loop in the next tick so that this function is
// completely async. It would be unexpected if `body` was called
// synchronously the first time.
Q.nextTick(loop);
// The promise
return done.promise;
}
// Usage
var index = 1;
promiseWhile(function () { return index <= 11; }, function () {
console.log(index);
index++;
return Q.delay(500); // arbitrary async
}).then(function () {
console.log("done");
}).done();
Run Code Online (Sandbox Code Playgroud)
law*_*nce 28
这是我发现表达基本模式的最简单方法:定义一个调用promise的函数,检查其结果,然后再次调用自身或终止.
const doSomething = value =>
new Promise(resolve =>
setTimeout(() => resolve(value >= 5 ? 'ok': 'no'), 1000))
const loop = value =>
doSomething(value).then(result => {
console.log(value)
if (result === 'ok') {
console.log('yay')
} else {
return loop(value + 1)
}
})
loop(1).then(() => console.log('all done!'))
Run Code Online (Sandbox Code Playgroud)
如果您使用的是解析或拒绝的承诺,您将定义then
而catch
不是使用if子句.
如果您有一系列承诺,您只需更改loop
为每次移动或弹出下一个.
编辑:这是一个使用的版本async/await
,因为它是2018年:
const loop = async value => {
let result = null
while (result != 'ok') {
console.log(value)
result = await doSomething(value)
value = value + 1
}
console.log('yay')
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它使用正常的while循环而不是递归.
jua*_*azo 19
我用一个对象来包装值.这样你就可以拥有一个done
属性来让循环知道你已经完成了.
// fn should return an object like
// {
// done: false,
// value: foo
// }
function loop(promise, fn) {
return promise.then(fn).then(function (wrapper) {
return !wrapper.done ? loop(Q(wrapper.value), fn) : wrapper.value;
});
}
loop(Q.resolve(1), function (i) {
console.log(i);
return {
done: i > 10,
value: i++
};
}).done(function () {
console.log('done');
});
Run Code Online (Sandbox Code Playgroud)
aar*_*sil 12
这是蓝鸟而不是q但是因为你没有特别提到q ..在bluebird api doc中,作者提到返回一个承诺生成函数比使用deferreds更惯用.
var Promise = require('bluebird');
var i = 0;
var counter = Promise.method(function(){
return i++;
})
function getAll(max, results){
var results = results || [];
return counter().then(function(result){
results.push(result);
return (result < max) ? getAll(max, results) : results
})
}
getAll(10).then(function(data){
console.log(data);
})
Run Code Online (Sandbox Code Playgroud)
小智 5
由于我不能评论Stuart K的答案,我会在这里补充一点.根据Stuart K的回答,您可以将其归结为一个非常简单的概念:重用未实现的承诺.他拥有的基本上是:
Stuart的答案是提供更通用的解决方案,但基础知识非常棒(一旦你意识到它是如何工作的).