Observable.subscribe()与Promise的异步/等待

时间:2019-04-27 18:46:47

标签: angular promise rxjs observable

Service中考虑以下两种方法来查询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;
}

第一个方法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);
}

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

我最近才真正开始理解,只有在您希望返回多个结果的情况下,才应真正使用此方法。换句话说,使用Promise<T>时,回调被调用的最大次数仅为一次。

由于我一直期望服务器仅总是返回一次,所以我的方法是否错误,我是否应该将Promise<T>方法与async/await结合使用?

3 个答案:

答案 0 :(得分:1)

我要说的是,在大多数情况下,您可以使用Promise,可观察对象可以做得更好!可观察项的一个主要优点是可以取消(通过取消订阅)。该功能在仅返回单个值时也很有用。

可观察到的用于处理多个并行异步请求的所有运算符功能要比手动将某些promise处理在一起要容易得多。

如果要避免取消订阅琐碎的可观察对象/订阅,则可以使用take(1)运算符函数,以确保不会发生意外的函数调用(如果您忘记取消订阅)。

这可以通过以下方式完成:

this.assessmentService.getAssessmentById(this.assessmentId)
 .pipe(take(1))
 .subscribe(result => 
 {
    this.assessment = result;
 });

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

答案 1 :(得分:1)

我认为您还必须记住热的和冷的可观察变量之间的区别(请参阅this question。由于httpClient是冷的可观察变量,因此它将为每个呼叫发出请求,而您不需要不用担心以后要取消订阅。这两种方法之间的主要区别是发出http请求的时间。在可观察的方法中,直到调用.subscribe时才发出请求。在promise版本中,请求将立即被接受。我同意@kasperlauge的观点,在大多数情况下,应首选可观察的物体。

答案 2 :(得分:0)

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