Angular HttpClient:如果 get() 失败,则执行 post()

Angular HttpClient: If get() fails, then execute a post()

我将 HttpClient 注入到服务中。我设置了一个 BehaviorSubject 来跟踪对该值的更改。我是 运行 一个带有 json-server 的模拟数据库。当我给它一些存在的东西时,我的服务能够正确执行 get(),但是如果我给它一些不存在的东西,它会给出 404。我希望它执行 post()。

对于现实世界的解释:用户有一个日历,其中包含每一天的每日日志。如果他们 select 一天存在日志,它将 get() 它。但是如果他们 select 一天不存在,则该服务应该 post() 服务器上的一个空白。回到那天会得到()之前创建的空白

这是我目前拥有的:

getCurrentDay(id: string) {
    this.http.get<DailyLog>(this.daysUrl + "/" + id).subscribe(data => {
      this._currentDailyLog.next(Object.assign({}, data));
    },
      error => {
        return console.log('Could not load daily log');
      }
    )
  }

对于未来的搜索者,这是我在@Poul Krujit 的帮助下得到的答案。我不得不根据他的建议更改两件事:post 的 url 不能像 get() 那样包含 /id 并且您需要将对象作为 [=25= 中的第二个参数]().

  getCurrentDay(id: string) {
    const url = `${this.daysUrl}/${id}`;

    this.http.get<DailyLog>(url).pipe(
      catchError(error =>
        error.status === 404
          ? this.http.post<DailyLog>(this.daysUrl, { "id": id, })
          : throwError(error)
      )
    ).subscribe({
      next: (data) => this._currentDailyLog.next({ ...data }),
      error: (error) => console.log('Could not load daily log:', error)
    });
  }

根据经验,您不应在服务中订阅 Observable。这使得调用者无法访问数据(或错误)。您应该使用运算符和 return Observable 而不是订阅。

让我们重构您的服务

export class SomeService {

  getCurrentDay(id: string) {
    return this.http.get<DailyLog>(this.daysUrl + "/" + id)
               .pipe(
                   /** catchError will be called if an exception is thrown
                   /*  and it expects you to return another Observable
                   /*  which is a great place to make another call
                    *  I assume post method will return newly created instance
                    */                   
                   catchError(err => this.http.post<DailyLog>(this.daysUrl + "/" + id)),
                   // also if you need to do some stuff within your service, you can use tap
                   tap(data => this._currentDailyLog.next(data))
                );
  }

}

上面的方法做的是尝试取回数据,如果出错会调用postapi和returnpost的结果。另外,一路更新 BehaviorSubject

注意:由于服务不再订阅,该方法的调用者必须订阅才能使所有内容运行(Observables默认是惰性的,不执行直到订阅)

您可以使用 catchError 运算符:

getCurrentDay(id: string) {
  const url = `${this.daysUrl}/${id}`;

  this.http.get<DailyLog>(url).pipe(
    catchError((error) => error.status === 404 
      ? this.http.post<DailyLog>(url)
      : throwError(error)
    )
  ).subscribe({
    next: (data) => this._currentDailyLog.next({ ...data })),
    error: (error) => console.log('Could not load daily log:', error)
  });
}