【问题标题】:Sequential Promises in typescript打字稿中的顺序承诺
【发布时间】:2022-01-02 11:23:34
【问题描述】:

我有一个带有 save 方法的 typescript 类,我希望下一次调用 save 方法,只有在第一个完成后才发生。 想象以下情况:

  count = 0;
  async save() {
      let x = this.count++;
      console.log("start " + x);
      await axios.post("***",{});
      console.log("end " + x);
  }
}

在这种情况下 - 当用户调用 save 时,无需等待 - 可以在第一个帖子完成之前调用第二个帖子 - 导致各种问题。

我想出的解决方案是:

  lastSave = Promise.resolve();
  count = 0;
  async save() {
    this.lastSave = this.lastSave.then(async () => {
      let x = this.count++;
      console.log("start " + x);
      await axios.post("***",{});
      console.log("end " + x);
    });
  }

这是一个有效的解决方案,还是有更好的方法?

【问题讨论】:

  • stackoverflow.com/questions/50269671/… (我倾向于更多地使用 Observables - 因为能够取消排队的事件。不知道你的目标是什么)。 rxmarbles.com
  • 这当然是有效的(就像代码一样),但我想这取决于你需要对这个过程进行多少控制,即一旦它们被调用,你就不能取消任何这些保存。正如另一位评论者所建议的那样,您可以使用 Observable 模式,甚至可以相当轻松地实现自己的承诺队列,以便每次保存都是一个离散事件,您可以与之交互,并在必要时在实际调用之前阻止。
  • 所有这一切都可以通过 Promise 轻松实现,并且对于重试或取消(使用跨平台内置 AbortController)等简单的事情不需要 observables。
  • 导致各种问题”——比如什么?

标签: typescript async-await promise


【解决方案1】:

then最后一个承诺的这种模式是完全有效的。您当前拥有的唯一问题是错误处理。在您当前的代码中,如果 一个 请求失败,它将失败所有未来的请求。

一个更完整的解决方案是这样的:

  lastSave = Promise.resolve();
  count = 0;
  async save() {
    const savePromise = this.lastSave.then(async () => {
      let x = this.count++;
      console.log("start " + x);
      await axios.post("***",{});
      console.log("end " + x);
    });
    // wait but don't fail forever on errors
    this.lastSave = savePromise.then(() => {}).catch(() => {});
    // You also need to return the promise so callers can react
    // to it. Note the lack of `.catch` here to not interfere with error handling
    return await savePromise; 
  }

【讨论】:

  • 我同意save() 应该返回一个promise 以便可以等待调用,但是不应该删除save 之前的async 关键字吗?
  • @md2perpe 认为asyncawait 仅在then 回调中且仅用于console.logs
  • 我说的不是.then(async () => { ... await ... }),而是async save() {。那不应该只是save() {吗?
  • @BenjaminGruenbaum 这是一个非常合理的解决方案,但它的用户应该知道它会重复:如果您调用 save 三次,它将进行三次服务器调用,即使第二次调用进行第三次过时的。人们可能期望这是 increment 服务器调用,但可能不是 saverefresh
  • @JeffBowman 我绝对同意,这是一个很好的观点,每当我们添加这种同步时,我们都会显着使代码更难调试和推理(这可能值得也可能不值得)。
猜你喜欢
  • 1970-01-01
  • 2018-02-04
  • 2020-03-10
  • 2018-12-19
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 2019-08-24
  • 1970-01-01
相关资源
最近更新 更多