setTimeOut循环中的promise:return resolve()或if-else

时间:2018-02-27 17:43:39

标签: loops promise return

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'))

1 个答案:

答案 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);
  }
}