最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Method chaining with asyncawait in TypeScript - Stack Overflow

programmeradmin1浏览0评论

I have a situation where I need to call an async method on the result of an async method.

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

Is there a good way to avoid the need to double await? I think I'd like to just do await container.getChild().getText();. What's the right way to make an API in TypeScript that will allow me to chain methods that return promises and then wait for the result with a single await?

EDIT: To clarify, this is more of an API design question. Is there a better pattern for doing what I'm trying to do (call an async method on an object returned by an async method)? Even if it means doing something totally different?

I have a situation where I need to call an async method on the result of an async method.

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

Is there a good way to avoid the need to double await? I think I'd like to just do await container.getChild().getText();. What's the right way to make an API in TypeScript that will allow me to chain methods that return promises and then wait for the result with a single await?

EDIT: To clarify, this is more of an API design question. Is there a better pattern for doing what I'm trying to do (call an async method on an object returned by an async method)? Even if it means doing something totally different?

Share Improve this question edited May 9, 2017 at 21:41 heathkit asked May 5, 2017 at 1:49 heathkitheathkit 5736 silver badges12 bronze badges 6
  • 5 To chain promises without using await, use .then. – castletheperson Commented May 5, 2017 at 1:53
  • 1 Just a quick note, your anonymous function discards the text without doing anything. I'm not sure if you intended that or not. You can replace the outer await with a return and that might do what you want. – Patrick Roberts Commented May 5, 2017 at 1:58
  • 3 You're awaiting two things, so why would you hope to be able to write a single await? If you were using promises, you'd have to use then twice as well. You can write const result = await container.getResult(); await result.getText();. – user663031 Commented May 5, 2017 at 2:33
  • 1 Replace the outer await with return :-) – Bergi Commented May 5, 2017 at 6:44
  • The await container.getChild().getText(); syntax is not possible when getChild returns a promise, as promises don't have a getText method. End of story. – Bergi Commented May 5, 2017 at 6:45
 |  Show 1 more ment

1 Answer 1

Reset to default 8

Is there a way to design my API better so that users won't need the double await? Even if it means changing the structure of my example drastically.

You must not make getResult asynchronous, it needs to return a Result instance right away so that further methods can be called on it. Your example is a bit weird since getChild doesn't really need to be asynchronous at all. But lets assume it is, and does some important.

You then could write

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();
  }
}

Now you can call parent.getResult().getText() directly. Basically, Result acts as a proxy wrapper around the Child class that does both the awaits. Maybe in your actual architecture you can even avoid the this.promise and do the child and text accesses in one step.

However, usually this is not worth it. Just let your caller await each step.

发布评论

评论列表(0)

  1. 暂无评论