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

查看:227
本文介绍了在setTimeOut循环中承诺:返回resolve()或if-else的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR:出现Promise的resolve()返回,这在循环函数中导致promise继续运行.调用resolve()来实现promise的正确方法是什么?

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:

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

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

推荐答案

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?

不要在非承诺的异步回调中做任何复杂的事情.

Not to do any complicated stuff in non-promise asynchronous callbacks.

在最低级别上承诺-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天全站免登陆