Как выполнить несколько вызовов API с помощью concatMap с условиями

#angular #rxjs #angular7

#angular #rxjs #angular7

Вопрос:

В Angular 7 я пытаюсь последовательно вызвать два разных метода API. Если первый из них прошел успешно, необходимо вызвать второй метод API.

Если первый код ответа API равен 500 внутренней ошибке сервера, тогда второй API не должен вызываться. Также мне нужно обрабатывать ошибки для каждого вызова API.

Я пробовал подход Promise, async и await, но когда я проверяю инструменты разработчика, вижу, что вызывается второй, даже если первый API не возвращает никакого ответа.

Может кто-нибудь, пожалуйста, помочь мне достичь этого, используя concatmap или любой другой угловой подход.

 public fetchandUpdate() {
    this.isSuccess= false;
    this.errorMessage = "";
    this.displayMessage = false;

     // First API call
      this.myService.getUserDetails(this.userid)
      .subscribe(
        (response) => {                           
          console.log('response received')
          this.userdetails= response;
        },
        (error) => {                              
          console.error('error caught in fetching user details')
          this.errorMessage = error;
          this.isSuccess= false;
        }
      )

    // Need to call this only if first API's response http status code is not 500
   if(firstAPIresponse.statuscode != 500)
   {
    this.myService.updateUserDetails(this.userdetails)
          .subscribe(
            (response) => {                           
              console.log('response received')
              this.isSuccess= true;
            },
            (error) => {                              
              console.error('error caught in updating user details')
              this.errorMessage = error;
              this.isSuccess= false;
            }
          )
      

     // This value should be updated only if above two is successful
      this.displayMessage=true;
    }
  }
 

Комментарии:

1. Возможно, вы захотите попробовать выполнить конвейер через switchMap или, альтернативно, преобразовать в promise и ожидать их. В настоящее время вы выполняете вызовы параллельно, и поэтому нет возможности использовать данные из первого или выполнить их условно

2. @Michael Не могли бы вы поделиться каким-либо примером URL-адреса для этого сценария.

Ответ №1:

Вы можете использовать switchMap для этого.

 // First API call
this.myService.getUserDetails(this.userid).pipe(
  // Logging is a side effect, so use tap for that
  tap(res => console.log('First API success', res)),
  // Call the second if first succeeds
  switchMap(resultFromUserDetails => this.myService.updateUserDetails(this.userdetails).pipe(
    // Handle your error for second call, return of(val) if succeeds or throwError() if you can't handle it here
    catchError(err => { 
      console.log('Error for second API (you can use statusCode here)', err);
      return of(); 
    }),
    // Logging is a side effect, so use tap for that
    tap(res => console.log('Second API success', res)),
  )),
  
  // Handle your error for first call, return of(val) if succeeds or throwError() if you can't handle it here
  catchError(err => { 
    console.log('Error for first API (you can use statusCode here)', err);
    return of(); 
  }) 
).subscribe(
  // handle both successfull
  resultFromUpdateUserDetails => {
    console.log('Both APIs succeeded, result from 2) is returned', resultFromUpdateUserDetails);
  },
  // handle uncaught errors
  err => {
    console.log('Any error NOT handled in catchError() or if you returned a throwError() instead of of() inside your catchError(), err);
  } 
)
 

Обновление: вы можете, конечно, выполнить некоторую логику внутри вашего switchMap

 this.myService.getUserDetails(this.userid).pipe(
   switchMap(res => {
     // do something with res, or other logic here

     // make sure to return your new observable at the end
     return this.myService.updateUserDetails(this.userdetails);
   })
);
 

Комментарии:

1. Я не мог понять раздел передачи ошибок. Не могли бы вы обновить ответ с помощью console.log (‘ошибка’) или (console.log(‘успех’) для каждого раздела. Это было бы очень полезно.

2. Кроме того, можно ли использовать логику if перед switchMap.

3. Также я могу проверить код состояния ошибки внутреннего сервера из первого ответа API.

4. Обновил мой ответ. Да, можно использовать логику внутри вашей switchMap. Просто убедитесь, что в конце возвращено новое наблюдаемое значение. Вы можете проверить код ошибки внутри вашего catchError(). Он выдает ту же ошибку, которую вы получили бы при втором обратном вызове в subscribe.