Observable.subscribe() 与带有 async/await 的 Promise

mon*_*_za 7 promise observable rxjs angular

考虑在 aService中查询 Web 服务的以下两种方法:

getAssessmentById(id: number): Observable<MotorAssessorReport> {
  const url = environment.endPoints.assessment.base + 
    environment.endPoints.assessment.assessmentById + id;
  return this.httpClient.get<MotorAssessorReport>(url)
}

async getAssessmentByIdAsync(id: number): Promise<MotorAssessorReport> {
  const url = environment.endPoints.assessment.base + 
    environment.endPoints.assessment.assessmentById + id;
   const data = await this.httpClient.get<MotorAssessorReport>(url).toPromise();
  return data;
}
Run Code Online (Sandbox Code Playgroud)

第一个方法,getAssessmentById返回一个observable. 第二种方法,getAssessmentByIdAsync,返回一个promise

subscribeToAssessment() {
 this.assessmentService.getAssessmentById(this.assessmentId).subscribe(result => 
 {
    this.assessment = result;
 });
}

async fetchAssessment() {
  this.assessment = await this.assessmentService.getAssessmentByIdAsync(this.assessmentId);
}
Run Code Online (Sandbox Code Playgroud)

我一直使用第一种方法,返回一个Observable<T>,并订阅我的调用代码。

我最近才真正开始明白,只有当您期望返回多个结果时,才应该真正使用这种方法。换句话说,当使用 a 时Promise<T>,回调被调用的最大数量只有一次。

由于我一直期望我的服务器总是只返回一次,我的方法是错误的,我应该使用这种Promise<T>方法,结合async/await?

小智 5

  • 如果您使用该服务来连续获取值,请使用可观察对象。
  • 如果您只需要获取一次数据,请使用承诺。您需要取消订阅可观察对象,否则会导致内存泄漏。
  • 仅在必要时使用异步等待,以防您的代码造成回调混乱。


小智 5

我认为您还必须记住热可观察量和冷可观察量之间的区别(请参阅此问题。由于httpClient是冷可观察量,因此它会为每次调用提出请求,并且您无需担心事后取消订阅。您的两种方法是在发出http请求时。在observable方法中,直到被调用后才会发出请求.subscribe。在promise版本中,会立即发出请求。我同意@kasperlauge,在大多数情况下,observables应该是首选。


小智 1

我想说的是,在大多数可以使用 Promise 的情况下,Observables 可以做得更好!可观察量的一个关键优点是它们可以被取消(通过取消订阅)。该功能在仅返回单个值时也很有用。

此外,处理多个并行异步请求的可观察量的所有运算符功能比手动编写一些 Promise 处理要容易得多。

如果您想避免取消订阅琐碎的可观察量/订阅,可以使用 take(1) 运算符函数,以确保您不会收到意外的函数调用(如果您忘记取消订阅)。

这将完成如下:

this.assessmentService.getAssessmentById(this.assessmentId)
 .pipe(take(1))
 .subscribe(result => 
 {
    this.assessment = result;
 });
Run Code Online (Sandbox Code Playgroud)

如果只需要简单的异步任务,则可以不需要 rxjs,可以使用 Promise 代替。从我的角度来看,使用 Promise 的优点是使用 async/await 的更清晰的语法和本机支持(不需要依赖第三方库)。