Search code examples
angularangular-httpclient

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


I have an HttpClient injected into a service. I have a BehaviorSubject set up to track changes to that value. I am running a mock db with json-server. My service is able to execute the get() correctly when I give it something that exists, but if I give it something that doesn't exist it will give a 404. I want it to execute a post().

For a real world explanation: the user has a calendar with a daily log for each day. If they select a day where a log exists, it will get() it. But if they select a day where one does not exist, the service should post() a blank one on the server. Going back to that day will get() the blank one created earlier.

This is what I have so far:

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');
      }
    )
  }

For future searchers, here is the answer I got with help from @Poul Krujit. I had to change 2 things from his suggestion: the url for the post cannot contain the /id like the get() and you need to give the object as the 2nd parameter in the post().

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

Solution

  • You can use the catchError operator:

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