【问题标题】:RxJs: Share an Observable using async / awaitRxJs:使用 async / await 共享一个 Observable
【发布时间】:2018-02-01 17:46:25
【问题描述】:

使用 RxJs 5 和 Angular 4。

我想共享一个 observable,这样我只发出 1 个 Http 请求,我还想等待调用,以便在我请求时得到结果。我有以下代码:

export class DataService {
    constructor(public http: HttpClient) {
        this.getObservable();  
    }

    public observable;

    public getObservable() {
        const url = "api/getData";
        this.observable = this.http.get(`${this.baseUrl}${url}`).share()
    }

    public async hasData(data: DataEnum) {        
        const result = await this.observable.toPromise();
        return result.filter(x => x === data).length > 0;
    }
}

然而,对 hasData 的多次调用会导致对我们的 api 端点的多次调用。我假设我已将observable 设置为共享的可观察对象,当我调用.toPromise() 时,它只会获取缓存的值并使其成为一个承诺,我可以await

它应该是这样工作的吗?

【问题讨论】:

  • 你为什么要这样做?我们可以帮助您获得更好的技术吗?
  • 如果你已经在使用 Promise,有什么东西会阻止你保存 Promise 吗?这将非常简单。共享运算符在这里无法正常工作。
  • @Microsmsm 代码已简化:) 当应用程序加载时,我需要知道将用户引导到哪里 - 因此需要等待结果。该数据还包含 HTML 模板中请求的其他一些信息,因此我们收到了很多电话,我想分享这些信息。
  • @estus 随意发布答案,这听起来很有希望!

标签: javascript angular rxjs


【解决方案1】:

由于share 的工作方式,observabletoPromise 上重新订阅,这会产生新的请求。

Promises 已经提供了缓存行为。考虑到 Promise 已经在服务 API 中使用,它们可以独占使用:

constructor(public http: HttpClient) {
    this.getPromise();  
}

public promise;

public getPromise() {
    const url = "api/getData";
    this.promise = this.http.get(`${this.baseUrl}${url}`).toPromise()
}

public async hasData(data: DataEnum) {        
    const result = await this.promise;
    return result.filter(x => x === data).length > 0;
}

【讨论】:

  • 感谢您的回答,这本来可以,但实际上路由保护数据解析器是修复它的“角度”方式。
【解决方案2】:

您的代码对我来说似乎过于复杂。我可能会做类似的事情:

private data = null;

getData():Observable<> {
  // if data is already available, return it immediately
  if (this.data) return Observable.of(this.data);

  // else, fetch from the server and cache result
  return this.http.get(url).do(data => this.data=data)
}

因此,只要您想要数据,您就可以:

this.getData().subscribe(
  data => console.log(data);
)

为确保您不会在数据到达之前多次调用 API 端点,您有几个选择。

  • 查看data resolvers - 在数据到达之前,这些不会初始化您的组件。在ngOnInit 中,数据将同步准备好,因此没有多次调用服务器的风险。

  • 或者,您可以使用*ngIf="data" 隐藏视图直到数据准备好,这样用户就不会多次单击按钮。

【讨论】:

  • 这里的问题是data是异步设置的,所以如果我连续两次快速调用getData()并且api调用需要一些时间,它会被调用两次。
  • @user917170 我在回答中添加了一些内容。
  • 好的,我认为数据解析器实际上是问题的正确解决方案,这在我的问题中并不一定很清楚,但是是的,我们希望阻止加载路由,直到服务调用返回。谢谢!
猜你喜欢
  • 2018-02-05
  • 2020-03-04
  • 2019-01-23
  • 2020-02-05
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
相关资源
最近更新 更多