TL; DR:似乎Promise的resolve()
返回,在循环函数中导致promise继续运行。调用resolve()来循环承诺的正确方法是什么?
详细说明:
我为动画目的构建了一个setTimeOut循环,它会运行很多次,然后退出循环。
完成后简单地调用resolve
不起作用:它确实解决了承诺,但随后继续运行。
function timeoutLoop (fcn, steps = -1, time = 0) {
return new Promise((resolve) => {
function timeoutStep () {
if (steps-- === 0) resolve() // steps will be -1
fcn()
setTimeout(timeoutStep, time)
console.log(steps)
}
timeoutStep()
})
}
timeoutLoop(() => {}, 10).then(() => console.log('done'))
两个修复工作:使用if-else
或使用if return resolve()
使用if-else
if (steps-- === 0) {
resolve() // steps will be -1
} else {
fcn()
setTimeout(timeoutStep, time)
console.log(steps)
}
返回resolve()调用
if (steps-- === 0) return resolve() // steps will be -1
我担心的是,即使两者都“有效”,也可能有副作用我不理解,例如调用堆栈保留了Promise体的调用框架。
在这种情况下,最佳做法是什么?
编辑:@Bergi使用异步函数给出的答案显然是正确的理念。我做了一个小改动,使用while循环而不是递归:
function timeoutPromise( ms = 1000) {
return new Promise(resolve => { setTimeout(resolve, ms) })
}
async function timeoutLoop (fcn, steps = -1, time = 0) {
while (steps-- !== 0) { // Note decr occurs *after* comparison
fcn()
await timeoutPromise(time)
}
}
timeoutLoop(() => {}, 10, 1000).then(() => console.log('done'))
答案 0 :(得分:1)
resolve()
不是语法,它不会像return
语句那样停止执行任何操作。您必须再次明确不再次调用setTimeout
以防止它发生。提前退货和else
都适合你。
在这种情况下,最佳做法是什么?
不要在非承诺异步回调中做任何复杂的事情。
在可能的最低级别 - setTimeout
函数上进行Promisify,仅限于此。用promises编写程序逻辑。
function delay(t) {
return new Promise(resolve => { setTimeout(resolve, t); });
}
async function timeoutLoop (fcn, steps = -1, time = 0) {
if (steps !== 0) {
fcn()
console.log(steps);
await delay(time)
return timeoutLoop(fcn, steps-1, time);
}
}