[英]Proper while() loop for bluebird promises (without recursion?)
I've been learning promises using bluebird for two weeks now. 我一直在学习使用蓝鸟两周的承诺。 I have them mostly understood, but I went to go solve a few related problems and it seems my knowledge has fell apart.
我对他们大多了解,但我去解决一些相关的问题,似乎我的知识已经崩溃了。 I'm trying to do this simple code:
我正在尝试这个简单的代码:
var someGlobal = true;
whilePromsie(function() {
return someGlobal;
}, function(result) { // possibly even use return value of 1st parm?
// keep running this promise code
return new Promise(....).then(....);
});
as a concrete example: 作为一个具体的例子:
// This is some very contrived functionality, but let's pretend this is
// doing something external: ajax call, db call, filesystem call, etc.
// Simply return a number between 0-999 after a 0-999 millisecond
// fake delay.
function getNextItem() {
return new Promise.delay(Math.random()*1000).then(function() {
Promise.cast(Math.floor(Math.random() * 1000));
});
}
promiseWhile(function() {
// this will never return false in my example so run forever
return getNextItem() !== false;
}, // how to have result == return value of getNextItem()?
function(result) {
result.then(function(x) {
// do some work ...
}).catch(function(err) {
console.warn("A nasty error occured!: ", err);
});
}).then(function(result) {
console.log("The while finally ended!");
});
Now I've done my homework! 现在我完成了我的作业! There is the same question, but geared toward Q.js here:
有同样的问题,但在这里面向Q.js:
Correct way to write loops for promise. 正确的写入循环的方法。
But the accepted answers, as well as additional answers: 但是接受的答案以及其他答案:
Now, there is an answer regarding RSVP that uses this async() method. 现在, 有关于使用此异步()方法RSVP答案。 And what really confuses me is bluebird documents and I even see code for a
Promise.async()
call in the repository, but I don't see it in my latest copy of bluebird. 真正令我困惑的是bluebird文档,我甚至在存储库中看到了
Promise.async()
调用的代码,但我在最新的bluebird副本中看不到它。 Is it in the git repository only or something? 它只在git存储库中还是什么?
It's not 100% clear what you're trying to do, but I'll write an answer that does the following things you mention: 这并不是100%清楚你想要做什么,但我会写一个答案来做你提到的以下事情:
First, let's assume you have some async function that returns a promise whose result is used to determine whether to continue looping or not. 首先,假设您有一些异步函数返回一个promise,其结果用于确定是否继续循环。
function getNextItem() {
return new Promise.delay(Math.random()*1000).then(function() {
return(Math.floor(Math.random() * 1000));
});
}
Now, you want to loop until the value returned meets some condition 现在,您希望循环,直到返回的值满足某些条件
function processLoop(delay) {
return new Promise(function(resolve, reject) {
var results = [];
function next() {
getNextItem().then(function(val) {
// add to result array
results.push(val);
if (val < 100) {
// found a val < 100, so be done with the loop
resolve(results);
} else {
// run another iteration of the loop after delay
setTimeout(next, delay);
}
}, reject);
}
// start first iteration of the loop
next();
});
}
processLoop(100).then(function(results) {
// process results here
}, function(err) {
// error here
});
If you wanted to make this more generic so you could pass in the function and comparison, you could do this: 如果你想让它更通用,那么你可以传递函数和比较,你可以这样做:
function processLoop(mainFn, compareFn, delay) {
return new Promise(function(resolve, reject) {
var results = [];
function next() {
mainFn().then(function(val) {
// add to result array
results.push(val);
if (compareFn(val))
// found a val < 100, so be done with the loop
resolve(results);
} else {
// run another iteration of the loop after delay
if (delay) {
setTimeout(next, delay);
} else {
next();
}
}
}, reject);
}
// start first iteration of the loop
next();
});
}
processLoop(getNextItem, function(val) {
return val < 100;
}, 100).then(function(results) {
// process results here
}, function(err) {
// error here
});
Your attempts at a structure like this: 您尝试这样的结构:
return getNextItem() !== false;
Can't work because getNextItem()
returns a promise which is always !== false
since a promise is an object so that can't work. 无法工作,因为
getNextItem()
返回一个始终为!== false
的promise,因为promise是一个对象,因此无法工作。 If you want to test a promise, you have to use .then()
to get its value and you have to do the comparson asynchronously so you can't directly return a value like that. 如果你想测试一个promise,你必须使用
.then()
来获取它的值,你必须异步执行comparson所以你不能直接返回这样的值。
Note: While these implementations use a function that calls itself, this does not cause stack build-up because they call themselves asynchronously. 注意:虽然这些实现使用调用自身的函数,但这不会导致堆栈堆积,因为它们会异步调用自身。 That means the stack has already completely unwound before the function calls itself again, thus there is no stack build-up.
这意味着在函数再次调用自身之前,堆栈已经完全展开,因此没有堆栈构建。 This will always be the case from a
.then()
handler since the Promise specification requires that a .then()
handler is not called until the stack has returned to "platform code" which means it has unwound all regular "user code" before calling the .then()
handler. 这将始终是
.then()
处理程序的情况,因为Promise规范要求在堆栈返回“平台代码”之前不调用.then()
处理程序,这意味着它已经解开所有常规“用户代码”之前调用.then()
处理程序。
Using async
and await
in ES7 在ES7中使用
async
和await
In ES7, you can use async and await to "pause" a loop. 在ES7中,您可以使用async并等待“暂停”循环。 That can make this type of iteration a lot simpler to code.
这可以使这种类型的迭代更容易编码。 This looks structurally more like a typical synchronous loop.
这在结构上看起来更像是典型的同步循环。 It uses
await
to wait on promises and because the function is declared async
, it always returns a promise: 它使用
await
等待promises,因为函数声明为async
,它总是返回一个promise:
function delay(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}
async function processLoop(mainFn, compareFn, timeDelay) {
var results = [];
// loop until condition is met
while (true) {
let val = await mainFn();
results.push(val);
if (compareFn(val)) {
return results;
} else {
if (timeDelay) {
await delay(timeDelay);
}
}
}
}
processLoop(getNextItem, function(val) {
return val < 100;
}, 100).then(function(results) {
// process results here
}, function(err) {
// error here
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.