setTimeOut 循环中的承诺:返回 resolve() 或 if-else [英] Promise in setTimeOut loop: return resolve() or if-else

查看:26
本文介绍了setTimeOut 循环中的承诺:返回 resolve() 或 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆