如何宣传这种递归函数

时间:2017-03-14 18:41:47

标签: javascript recursion ecmascript-6 es6-promise

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

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

animate(999).then(...)

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

animate(999)
&#13;
&#13;
&#13;

更新

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

&#13;
&#13;
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))
&#13;
&#13;
&#13;

**工作更新(但不了解)**

&#13;
&#13;
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))
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:4)

setTimeout(() => {animate(length)}, 10)不起作用,这可能会再次调用animate函数,但永远不会解析在最外层调用中创建的承诺(这就是你的&#34;工作更新&#34;修复 - 它使用递归调用的promise来解析外部promise,这将导致它们以相同的结果实现。)

而不是乱用回调,promisify你正在使用的异步原语,setTimeout

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

然后在动画函数中使用它来始终返回一个promise:

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

答案 1 :(得分:2)

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

如果您已将Promise((resolve, reject)放在该功能上,那么它可以正常工作。

或者你随身携带resolve, reject

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

async / await

是一项出色的工作

&#13;
&#13;
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!"));
&#13;
&#13;
&#13;