在TypeScript中使用async/await进行方法链编程

8

我有一个情况,需要在异步方法的结果上调用另一个异步方法。

class Parent {
  constructor(private child: Child) { }

  private getChild(): Promise<Child> {
    return Promise.resolve(this.child);
  }

  async getResult(): Promise<Child> {
     return await this.getChild()
  }
}

class Child {
  getText(): Promise<string> {
    return Promise.resolve('text');
  }
}

let child = new Child();
let container = new Parent(child);

let printText = async () => {
  await (await container.getResult()).getText();
}

printText();

有没有什么好的方法可以避免需要双重等待?我想只需执行 await container.getChild().getText(); 即可。在 TypeScript 中,如何制作一种 API,使我能够链接返回承诺的方法,然后使用单个 await 等待结果?
编辑:为了澄清,这更多是一个 API 设计问题。有没有更好的模式来做我试图做的事情(调用由异步方法返回的对象上的异步方法)?即使这意味着完全不同的事情?

5
若想在不使用await的情况下链接多个Promise,请使用.then - 4castle
1
只是一个小提醒,你的匿名函数在不执行任何操作的情况下丢弃了文本。我不确定你是否有意这样做。你可以将外部的 await 替换为 return,这可能会达到你想要的效果。 - Patrick Roberts
3
你正在等待两件事情,所以为什么希望能够写一个 await?如果你在使用 Promises ,那么你也必须要使用 then 两次。你可以写成 const result = await container.getResult(); await result.getText(); - user663031
1
return替换外部的await :-) - Bergi
getChild返回一个Promise时,await container.getChild().getText();语法是不可能的,因为Promise没有getText方法。故此无可厚非。 - Bergi
是的,这个例子有点过于简单了。我想我在问一个API设计问题。是否有一种更好的方式来设计我的API,以便用户不需要双重等待?即使这意味着彻底改变我的示例结构。 - heathkit
1个回答

8
有没有更好的方法来设计我的API,让用户不需要使用双重等待?即使这意味着彻底改变我的示例结构。
您不能将“getResult”设置为异步的,它需要立即返回一个“Result”实例,以便可以在其上调用其他方法。您的示例有点奇怪,因为“getChild”根本不需要是异步的。但是假设它是,并且执行一些重要操作。
然后,您可以编写如下代码:
class Parent {
  private async getChild(): Promise<Child> {
    … // whatever
  }

  getResult(): Result {
     return new Result(this.getChild())
  }
}
class Result {
  constructor(p: Child) {
    this.promise = p;
  }
  async getText(): Promise<string> {
    return (await this.promise).getText();
  }
}

现在你可以直接调用parent.getResult().getText()。基本上,Result充当了代理包装器,围绕着Child类执行等待操作。也许在您实际的架构中,甚至可以避免使用this.promise,并在一步中进行子级和文本访问。
然而,通常这并不值得。只需让您的调用者await每个步骤即可。

没错,我的例子是人为制造的,不一定需要是异步的。谢谢,这就是我想要的!我同意,只让人们明确地使用 await 可能更好,但我只是想探索一下我的选择。 - heathkit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接