简体   繁体   English

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

[英]rxjs observable.pipe(take(1)) vs toPromise

Recently I've been moved to a new project which uses angular 6 as frontend framework and spring for REST services.最近我被转移到一个新项目,该项目使用 angular 6 作为前端框架和 REST 服务的 spring。

The project is in development for 2 years now and what I've observed was that almost all HTTP request made with angular HttpClient is then piped to take filter from rxjs.该项目已经开发了 2 年,我观察到几乎所有使用 angular HttpClient 发出的 HTTP 请求都通过管道从 rxjs 中获取过滤器。 All REST APIs emit only one value.所有 REST API 只发出一个值。 There's no need for manual cancellation and the laziness property of observables.不需要手动取消和 observable 的惰性属性。

My intuition is that using toPromise() would be a better way to code.我的直觉是使用 toPromise() 将是更好的编码方式。

What are your thoughts?你怎么看?

  //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
      })
  }

My proposed approach:我建议的方法:

  //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
      })
  }

I think that my approach is better because it is strongly typed and it's cleaner.我认为我的方法更好,因为它是强类型的并且更干净。

Actually the accepted answer is misleading by saying that transforming an observable to a promise is like taking a step backward.实际上,公认的答案是误导,说将 observable 转换为 promise 就像倒退一步。 Rather it's about what your needs are.而是关于您的需求。 as stated in Angular Documentation :Angular 文档中所述

Observables differentiate between chaining and subscription. Observable 区分链接和订阅。 Promises only have .then() clauses. Promise 只有 .then() 子句。 This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.这使得 observable 可用于创建复杂的转换配方以供系统的其他部分使用,而不会导致工作被执行。

And the difference between toPromise() and take(1) (or for short use operator first()), is that take(1) completes after the 1st value emitted, while toPromise waits for the last emitted value (waits for the observable to complete then resolves the last value emitted). toPromise() 和 take(1)(或简称使用 operator first())之间的区别在于,take(1) 在第一个值发出后完成,而 toPromise 等待最后发出的值(等待可观察到的值)完成然后解析最后发出的值)。

Another difference between observables and promises that might interest you, is that Observable subscriptions are cancellable while promises are not.您可能会感兴趣的 observables 和 promises 之间的另一个区别是 Observable 订阅是可取消的,而 promises 则不可取消。 As a concrete example, say your API /customers takes time but you dont need the results anymore and you navigate to another page, unsubscribing cancels the HTTP request.举一个具体的例子,假设您的 API /customers 需要时间,但您不再需要结果并导航到另一个页面,取消订阅会取消 HTTP 请求。

As you mentioned strongly typed we can do the same in observable approach.正如您提到的强类型,我们可以在 observable 方法中做同样的事情。


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

  //component.ts
  public ngOnInit() {
      this.customerService.getCustomers()
      .pipe(take(1))
      .subscribe((customers: Array<Customer>) => {
       //do some stuff
       });
  }

  • For HttpRequest with single HttpResponse you may rely on promise approach.对于带有单个 HttpResponse 的 HttpRequest,您可能依赖于promise方法。
  • But HttpRequest with multiple response such as progress/stream of data(blob) go for the Observable approach.但是 HttpRequest 具有多个响应,例如进度/数据流(blob)采用Observable方法。

Try to use Observable as much as possible, once you familiar with you wont go for other options.尽量使用 Observable,熟悉了就不会再选择其他的了。 So Give it a try!所以试试吧!

I recommend to keep using the Observable way.我建议继续使用 Observable 方式。

Why?为什么? Because later it will be easier to:因为以后会更容易:

  • build upcoming logic (like mapping, filtering, etc.) for planned features为计划的功能构建即将到来的逻辑(如映射、过滤等)
  • use the code, due mixing the two approach makes it harder to read/write使用代码,由于混合这两种方法会使读/写变得更加困难

On the other hand you have right, your code is more readable as the code from others, but you can also change the Observable to be as good as yours (just add strong typing to it), and it still keeps the functionality and consistency of the Observables.另一方面,您是对的,您的代码比其他人的代码更具可读性,但是您也可以将 Observable 更改为与您的代码一样好(只需为其添加强类型),并且它仍然保持功能和一致性可观察对象。

Going from observables to promises is a step back.从 observables 到 promises 是一个退步。

It's like going from a Porsche 911 to a Fiat multipla.这就像从保时捷 911 变成了菲亚特 multipla。

So no, you shouldn't use toPromise() , and no, your way isn't "better" (that's some ego there buddy !)所以不,你不应该使用toPromise() ,不,你的方式不是“更好”(那是一些自负的哥们!)

I think that my approach is better because it is strongly typed and it's cleaner.我认为我的方法更好,因为它是强类型的并且更干净。

Typing an HTTP answer isn't depending on pormises or observables, but on the developer himself.键入 HTTP 答案并不取决于 pormises 或 observables,而是取决于开发人员自己。 And cleaner is a matter of perspective, personally I hate seeing toPromise() s.清洁是一个视角问题,我个人讨厌看到toPromise() s。

And the major drawback of your solution is that once converted to a promise, you can't pipe anything anymore, making your functions less versatile.您的解决方案的主要缺点是,一旦转换为承诺,您就无法再通过管道传输任何东西,从而使您的功能变得不那么通用。

But their code isn't the best either.但他们的代码也不是最好的。 Usually this kind of behavior is used for stores and caches, are you sure you didn't omit something ?通常这种行为用于存储和缓存,你确定你没有遗漏什么吗?

Anyway, if not, and I only rely on the code provided, this would be the right code :无论如何,如果没有,我只依赖提供的代码,这将是正确的代码:

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

....

public ngOnInit() {
  this.customerService.getCustomers()
    .subscribe((customers) => {...})
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM