【问题标题】:How to Promisify this recursive function如何 Promisify 这个递归函数
【发布时间】:2017-03-14 18:41:46
【问题描述】:
下面是一个简单的递归函数,它接受一个长度,并使用setTimeout 递减它。一旦长度为<= 0,就完成了。
我如何编写这个函数(在纯 JavaScript 中)以便我可以像这样使用它:
animate(999).then(...)
const animate = length => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return
}
setTimeout(() => {animate(length)}, 10)
}
animate(999)
更新:
这是我尝试过的。我遇到的问题是,resolve 似乎没有被调用,或者被不同的承诺调用。
const animate = length => {
return new Promise((resolve, reject) => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
resolve(true)
return // without this the function runs forever
}
setTimeout(() => {animate(length)}, 10)
})
}
animate(999).then(result => console.log(result))
** 工作更新(但不明白)**
const animate = length => {
return new Promise((resolve, reject) => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return resolve(true)
}
setTimeout(() => {resolve(animate(length))}, 10)
})
}
animate(999).then(result => console.log(result))
【问题讨论】:
标签:
javascript
recursion
ecmascript-6
es6-promise
【解决方案1】:
setTimeout(() => {animate(length)}, 10) 将不起作用,这可能会再次调用 animate 函数,但永远不会解决在最外层调用中创建的承诺(这是您的“工作更新”修复的内容 - 它使用来自递归调用,这将使它们实现相同的结果)。
不要搞那么多回调,promisify 您正在使用的异步原语setTimeout:
function wait(t) {
return new Promise(resolve => {
setTimeout(resolve, t);
});
}
然后在你的动画函数中使用它来始终返回一个承诺:
const animate = length => {
console.log(length)
length -= 10
if (length <= 0) {
length = 0
return Promise.resolve()
}
return wait(10).then(() => {
return animate(length)
})
}
【解决方案2】:
每次都会生成一个新的Promise 以及它的resolve 和reject,因为您在每个setTimeout 函数调用上都返回一个新的Promise 并且只解析最新的一个(内部的那个) if (length <= 0))。
如果您将Promise((resolve, reject) 放在函数上,它会正常工作。
或者你随身携带resolve, reject。
【解决方案3】:
只是为了好玩,你可以这样做。你不应该。代码无法维护。
const animate = (length, resolve) => {
var promise;
if (!resolve) {
promise = new Promise((newResolve) => {
resolve = newResolve;
});
}
console.log(length);
length -= 10;
if (length <= 0) {
length = 0;
resolve(true);
return promise;
}
setTimeout(() => {animate(length, resolve)}, 10);
return promise;
}
animate(999).then(result => console.log(result))
【解决方案4】:
这是async/await 的出色工作:
let wait = ms => new Promise(resolve => setTimeout(resolve, ms));
const animate = async length => {
for (; length > 0; length -= 10) {
console.log(length);
await wait(10);
}
return 0;
}
animate(999).then(() => console.log("Done!"));