setTimeOut 循环中的承诺:返回 resolve() 或 if-else [英] Promise in setTimeOut loop: return resolve() or if-else
问题描述
TL;DR:看起来 Promise 的 resolve()
返回,它在循环函数中导致 Promise 继续运行.调用 resolve() 循环承诺的正确方法是什么?
TL;DR: It appears Promise's resolve()
returns, which in a looping function causes the promise to keep running. What's the proper way to call resolve() for looping promises?
详情:
我为动画目的构建了一个 setTimeOut 循环,该循环将运行多次,然后退出循环.
Details:
I built a setTimeOut loop for animation purposes which would run for a number of times, then exit the loop.
在完成后简单地调用 resolve
不起作用:它确实解决了承诺,但随后继续运行.
Simply calling resolve
when done did not work: it did resolve the promise but then kept running.
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()
Two fixes worked: use an if-else
or have the if use return resolve()
使用 if-else
if (steps-- === 0) {
resolve() // steps will be -1
} else {
fcn()
setTimeout(timeoutStep, time)
console.log(steps)
}
返回 resolve() 调用
return the resolve() call
if (steps-- === 0) return resolve() // steps will be -1
我担心的是,即使两者都工作",也可能存在我不理解的副作用,例如调用堆栈保留 Promise 主体的调用框架.
My concern is that, even if both "work", there may be side effects I don't understand such as the call-stack retaining the call frame of the Promise body.
在这种情况下,最佳做法是什么?
What's the best practice in this case?
@Bergi 给出的答案,使用异步函数,显然是正确的哲学.我确实做了一个小改动,使用 while 循环而不是递归:
The answer @Bergi gave, using async functions, is clearly the right philosophy. I did make one minor change, using a while loop rather than recursion:
函数 timeoutPromise(ms = 1000) {return new Promise(resolve => { setTimeout(resolve, ms) })}异步函数 timeoutLoop (fcn, steps = -1, time = 0) {while (steps-- !== 0) {//注意 decr *after* 比较发生fcn()等待超时承诺(时间)}}timeoutLoop(() => {}, 10, 1000).then(() => console.log('done'))
推荐答案
resolve()
不是语法,它不会像 return
语句那样停止执行任何事情.您必须再次明确不调用 setTimeout
以防止它发生.提前返回和 else
都适合你.
resolve()
is not syntax, it does not stop execution of anything like a return
statement does. You have to explicitly not call setTimeout
again to prevent it from occurring. Both early return and else
work fine for you there.
在这种情况下,最佳做法是什么?
What's the best practice in this case?
不要在 non-promise 异步回调中做任何复杂的事情.
Not to do any complicated stuff in non-promise asynchronous callbacks.
Promisify 在可能的最低级别 - setTimeout
函数,仅此而已.用 Promise 编写程序逻辑.
Promisify on the lowest possibly level - the setTimeout
function and only that. Write your program logic with 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);
}
}
这篇关于setTimeOut 循环中的承诺:返回 resolve() 或 if-else的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!