В контексте компонента Angular у меня есть 2 наблюдаемых.
Требования
Подход
Как лучше всего удовлетворить мои требования?
getData1$ = this.myService.getData1();
getData2$ = this.myService.getData2();
constructor(private myService: MyService) {
this.getAllData();
}
getAllData() {
concat(this.getData1$, this.getData2$)
.pipe(finalize(() => console.info('always called')))
.subscribe(() => {
error: console.info('one or more data fetches have had an error');
complete: console.info('all data fetches have succeeded');
});}
Используйте concat , он будет выполняться последовательно один за другим, затем мы можем использовать toArray, который соберет все выбросы источника и выдаст их в виде массива, когда источник завершится.
getData1$ = this.myService.getData1();
getData2$ = this.myService.getData2();
constructor(private myService: MyService) {
this.getAllData();
}
getAllData() {
concat(this.getData1$, this.getData2$).pipe(toArray())
.subscribe({
next: (data: any) => console.info('success!'),
error: () => console.info('one or more data fetches have had an error'),
complete: () => console.info('all data fetches have succeeded'),
});
}
@Fred2020, пожалуйста, поделитесь стекблицем с неудачным сценарием и тем, что нужно исправить, насколько я вижу, мой код соответствует вашим требованиям стекблиц с неудачным наблюдаемым
Попробуйте.... const arraySource = concat( of(1), throwError(new Error('Error')) ).pipe(toArray());
@Fred2020 это работает stackblitz
Приношу извинения, это работает с добавленным обработчиком ошибок.
А как насчет требования «Если первое наблюдаемое не работает, я не запускаю второе»? В вашем примере второй наблюдаемый объект, скорее всего, будет вызван, даже если он не подписан (HttpService создает горячие наблюдаемые объекты).
@Liero Невозможно преобразовать завершенный API в неисправный API, это пример не всего API, но он будет работать, если вы работаете с вызовами API
С помощью следующего кода я достиг желаемого результата в Angular 18:
concat(this.getData1$, this.getData2$)
.pipe(takeUntil(this.destroy$)) // You dont need it, but it wouldnt hurt.
.subscribe({
next: (res) => {
//This logs if a request is successful.
console.info(res);
},
error: (err) => {
//This logs if a request is NOT successful.
console.info('Error');
},
complete: () => {
//This logs if ALL requests are successful.
console.info('Complete');
},
});
Это запустит Observables последовательно.
Если один из них потерпит неудачу, он зарегистрирует ошибку и остановится.
Если он пройдет, он зарегистрирует каждый ответ и зарегистрирует его в конце.
Не хватает только finalize
, так как при подписке у меня возникли ошибки.
Итак, чем отличается ваш Кодекс?
Вместо .subscribe(() => {...})
я использую .subscribe({...})
Кстати, это то, что я использую для уничтожения $:
destroy$ = new Subject<void>();
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
«Если он пройдет, он зарегистрирует каждый ответ и зарегистрирует его в конце». Это не соответствует требованию 4
@Fred2020 Fred2020 Просто удалите журнал внутри next
. Тогда он не будет регистрировать каждый ответ и выполнит все ваши требования.
Я не уверен, что соблюдаю требование 4: «Если оба успешны, я хочу зарегистрировать одно сообщение об успехе» ... поэтому я хочу, чтобы было зарегистрировано сообщение, одно для обоих успешных запусков, а не 1 для каждого успешного запуска.
@Fred2020 Да. next
логи для каждого запроса. error
журналы каждого неудачного запроса. complete
регистрирует, все ли запросы выполнены успешно. Поэтому, если вам нужен только один журнал, если оба успешны, удалите любой журнал внутри следующего. Тогда он будет регистрироваться только при ошибках или если оба пройдут без проблем.
Привет, Нарен, спасибо за ответ. Однако решение в предоставленной демонстрации Stackblitz не отвечает этим требованиям. Вы можете увидеть, выдает ли одна из наблюдаемых ошибку, например, она не соответствует требованиям.