可以在 waitOneCycle.then(waitOneCycle().then(...)) 中编写一系列 promises 和 then handlers 但没有深度嵌套吗?

Can a series of promises and then handlers be written in waitOneCycle.then(waitOneCycle().then(...)) but without deep nesting?

如果我们已经有

const waitOneCycle = () => {
  return new Promise(resolve => setTimeout(resolve));
};

然后是我们的代码(目前在 Jest 和 SinonJS 中使用,虽然不一定是:)

waitOneCycle()
  .then(() => {
    // do something

  });

它读起来真的很优雅:waitOneCyclethen 做了一些事情。

但是,如果我们进行一系列操作,我们必须:

waitOneCycle()
  .then(() => {
    // do something

    return waitOneCycle();
  })
  .then(() => {
    // do something

    return waitOneCycle();
  })
  .then(() => {
    // do something

    return waitOneCycle();
  });

它读起来很奇怪,因为我们为什么要 return 一些东西来充当“waitOneCycle”?这是它的工作方式,但代码只是以一种奇怪的方式读取。

我们可以这样做:

waitOneCycle()
  .then(() => {

    // not return anything here
  })
  .then(() => {
    waitOneCycle()
      .then(() => {

      });
  })

但这会回到过去的嵌套地狱问题。有没有办法重构它,使其读取连贯,但同时所有操作都被序列化?

P.S。在 Ruby 的情况下,如果以这种方式链接承诺,它实际上可以很好地读出,因为我们不需要使用 return 作为最后评估的值。所以它读起来像 waitOneCyclethenwaitOneCyclethen...而且看起来很优雅。

你不需要嵌套(而且它只有在你要 return 内在承诺时才有效),你也可以链接它:

waitOneCycle()
  .then(() => {
    // do something
  })
  .then(waitOneCycle)
  .then(() => {
    // do something
  })
  .then(waitOneCycle)
  .then(() => {
    // do something
  })
  .then(waitOneCycle);

如果让 waitOneCycle 传递以下值,这可能会更好:

const waitOneCycle = (v) => {
  return new Promise(resolve => setTimeout(resolve, v));
};

当然,如果你想要阅读连贯且没有嵌套的承诺代码(甚至 then 回调的代码也不行),你应该只使用 async/await 语法.