#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.