rxjs observable.pipe(take(1)) 与 toPromise

Geo*_*ida 5 javascript observable rxjs typescript angular

最近我被转移到一个新项目,该项目使用 angular 6 作为前端框架和 REST 服务的 spring。

该项目已经开发了 2 年,我观察到几乎所有使用 angular HttpClient 发出的 HTTP 请求都通过管道从 rxjs 中获取过滤器。所有 REST API 只发出一个值。不需要手动取消和 observable 的惰性属性。

我的直觉是使用 toPromise() 将是更好的编码方式。

你怎么看?

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() {
     return http.get('/customers');
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().pipe(take(1)).subscribe((customers) => {
           //do some stuff
      })
  }
Run Code Online (Sandbox Code Playgroud)

我建议的方法:

  //customer-service.ts
  constructor(private http: HttpClient) {

  }

  public getCustomers() : Promise<Array<Customer>> {
     return http.get('/customers').toPromise();
  }

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers().then((customers: Array<Customer>) => {
         //do some stuff
      })
  }
Run Code Online (Sandbox Code Playgroud)

我认为我的方法更好,因为它是强类型的并且更干净。

小智 5

实际上,公认的答案是误导,说将 observable 转换为 promise 就像倒退一步。而是关于您的需求。如Angular 文档中所述

Observables 区分链接和订阅。Promise 只有 .then() 子句。这使得 observable 可用于创建复杂的转换配方以供系统的其他部分使用,而不会导致工作被执行。

toPromise() 和 take(1)(或简称使用 operator first())之间的区别在于,take(1) 在第一个值发出后完成,而 toPromise 等待最后发出的值(等待可观察到的值)完成然后解析最后发出的值)。

您可能会感兴趣的 observables 和 promises 之间的另一个区别是 Observable 订阅是可取消的,而 promises 则不可取消。举一个具体的例子,假设您的 API /customers 需要时间,但您不再需要结果并导航到另一个页面,取消订阅会取消 HTTP 请求。


小智 -10

从可观察到的承诺是一个倒退。

这就像从保时捷 911 到菲亚特 multipla 一样。

所以不,你不应该使用toPromise(),不,你的方法并不“更好”(这是一些自我意识,伙计!)

我认为我的方法更好,因为它是强类型的并且更干净。

输入 HTTP 答案并不取决于承诺或可观察结果,而是取决于开发人员本人。清洁是一个视角问题,我个人讨厌看到toPromise()s。

您的解决方案的主要缺点是,一旦转换为承诺,您就无法再通过管道传输任何内容,从而使您的功能不太通用。

但他们的代码也不是最好的。通常这种行为用于存储和缓存,你确定你没有遗漏什么吗?

无论如何,如果没有,并且我只依赖提供的代码,这将是正确的代码:

public getCustomers() {
  return http.get<Customer[]>('/customers');
}

....

public ngOnInit() {
  this.customerService.getCustomers()
    .subscribe((customers) => {...})
}
Run Code Online (Sandbox Code Playgroud)

  • 如此愚蠢的贬义评论。更好的比喻是,如果你只需要一辆菲亚特,但继续开一辆保时捷,那么当你不使用保时捷的所有功能时,你的维护成本将是原来的 10 倍。@George,请考虑删除您接受的答案。将仅触发一个事件的可观察对象转变为承诺,使您的代码更易于遵循和使用,您无需担心处理被多次调用的回调,也无需取消订阅。 (3认同)