【问题标题】:How to Promisify this recursive function如何 Promisify 这个递归函数
【发布时间】:2017-03-14 18:41:46
【问题描述】:

下面是一个简单的递归函数,它接受一个长度,并使用setTimeout 递减它。一旦长度为<= 0,就完成了。

我如何编写这个函数(在纯 JavaScript 中)以便我可以像这样使用它:

animate(999).then(...)

const animate = length => {
  console.log(length)
  length -= 10
  if (length <= 0) {
    length = 0
    return
  }
  setTimeout(() => {animate(length)}, 10)
}

animate(999)

更新:

这是我尝试过的。我遇到的问题是,resolve 似乎没有被调用,或者被不同的承诺调用。

const animate = length => {
  return new Promise((resolve, reject) => {
    console.log(length)
    length -= 10
    if (length <= 0) {
      length = 0
      resolve(true)
      return // without this the function runs forever
    }
    setTimeout(() => {animate(length)}, 10)
  })
}

animate(999).then(result => console.log(result))

** 工作更新(但不明白)**

const animate = length => {
  return new Promise((resolve, reject) => {
    console.log(length)
    length -= 10
    if (length <= 0) {
      length = 0
      return resolve(true)
    }
    setTimeout(() => {resolve(animate(length))}, 10)
  })
}

animate(999).then(result => console.log(result))

【问题讨论】:

    标签: javascript recursion ecmascript-6 es6-promise


    【解决方案1】:

    setTimeout(() =&gt; {animate(length)}, 10) 将不起作用,这可能会再次调用 animate 函数,但永远不会解决在最外层调用中创建的承诺(这是您的“工作更新”修复的内容 - 它使用来自递归调用,这将使它们实现相同的结果)。

    不要搞那么多回调,promisify 您正在使用的异步原语setTimeout

    function wait(t) {
        return new Promise(resolve => {
            setTimeout(resolve, t);
        });
    }
    

    然后在你的动画函数中使用它来始终返回一个承诺:

    const animate = length => {
      console.log(length)
      length -= 10
      if (length <= 0) {
        length = 0
        return Promise.resolve()
      }
      return wait(10).then(() => {
        return animate(length)
      })
    }
    

    【讨论】:

      【解决方案2】:

      每次都会生成一个新的Promise 以及它的resolvereject,因为您在每个setTimeout 函数调用上都返回一个新的Promise 并且只解析最新的一个(内部的那个) if (length &lt;= 0))。

      如果您将Promise((resolve, reject) 放在函数上,它会正常工作。

      或者你随身携带resolve, reject

      【讨论】:

        【解决方案3】:

        只是为了好玩,你可以这样做。你不应该。代码无法维护。

        const animate = (length, resolve) => {
          var promise;
          
          if (!resolve) {
            promise = new Promise((newResolve) => {
              resolve = newResolve;
            });
          }
          
          console.log(length);
          length -= 10;
          
          if (length <= 0) {
            length = 0;
            resolve(true);
            return promise;
          }
          
          setTimeout(() => {animate(length, resolve)}, 10);
          
          return promise;
        }
        
        animate(999).then(result => console.log(result))

        【讨论】:

          【解决方案4】:

          这是async/await 的出色工作:

          let wait = ms => new Promise(resolve => setTimeout(resolve, ms));
          
          const animate = async length => {
            for (; length > 0; length -= 10) {
              console.log(length);
              await wait(10);
            }
            return 0;
          }
          
          animate(999).then(() => console.log("Done!"));

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-08-21
            • 2011-03-29
            • 2017-02-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多