我是rxjs的新手,我想弄清楚以下代码中发生了什么。
实际上,为了说明这个想法,我准备了两个简单的Promise(resolvePromise和rejectPromise),一个解决了一个Promise,另一个拒绝了。 “主题”实例用于触发这两个承诺(通过mergeMap和forkJoin用管道传输)。最后,添加了两个单独的指令(source $ .next('xxx')),希望触发两次订阅。
但是最后,只有第一个“ source $ .next('1')”会触发订阅,而下一个“ source $ .next('2')”似乎什么也没做。
我猜这是由拒绝承诺引起的,它实际上是“引发异常”。 但是我想知道如何解决此代码,以便第二个“ source $ .next('2')”也将触发订阅。
非常感谢
import { of,forkJoin,Subject } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const resolvePromise = val =>
new Promise(resolve => resolve(`resolve value: ${val}`));
const rejectPromise = err =>
Promise.reject(`reject error: ${err}`);
const source$ = new Subject();
source$
.pipe(mergeMap(val => {
return forkJoin([
resolvePromise(val),
rejectPromise(val)
]);
}))
.subscribe(
console.log,
console.error
);
source$.next('1');
source$.next('2');
基于下面的AndreiGătej的建议,为了克服此问题,我选择在forkJoin之后传递一个catchError,并将错误处理放入其中。
source$.pipe(
mergeMap(val => {
return forkJoin([
resolvePromise(val),
rejectPromise(val)
])
.pipe(
catchError(err => {
// your error handling business logic
console.error(err);
return empty();
})
);
}))
.subscribe(console.log);
答案 0 :(得分:1)
拒绝承诺,实际上是“引发异常”
从RxJS内部处理诺言的角度来看,我说您是对的:
promise.then(
(value) => {
if (!subscriber.closed) {
subscriber.next(value);
subscriber.complete();
}
},
(err: any) => subscriber.error(err) // !
)
还有一点值得一提的是,正如您从上面的代码段中看到的那样,当承诺第一次解决时,已解决的值和一个complete
通知就会过去了。
complete
部分对于forkJoin
运算符非常重要。
forkJoin
订阅所有提供的可观察对象,并等待,直到全部完成。仅当可观察对象至少发射一次 时,才会发送具有值的数组。
当一个可观察对象发出error
通知时,forkJoin
将立即在链中进一步发送该error
通知。
这是我的方法:
ource$
.pipe(mergeMap(val => {
return forkJoin([
resolvePromise(val),
from(rejectPromise(val)).pipe(catchError(err => of(err)))
]);
}))
.subscribe(
console.log,
console.error
);
我们正在使用from
,以便我们可以拦截尽早承诺错误,这使我们可以使用catchError
并使用可观察值,它将发送一个值,然后complete
通知(of(err)
)。
答案 1 :(得分:0)
您需要通过retry
或repeat
重新订阅。
import { of,forkJoin,Subject } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const resolvePromise = val =>
new Promise(resolve => resolve(`resolve value: ${val}`));
const rejectPromise = err =>
Promise.reject(`reject error: ${err}`);
const source$ = new Subject();
source$.pipe(
mergeMap(val => forkJoin([
resolvePromise(val),
rejectPromise(val)
])),
catchError(() => EMPTY),
repeat(),
).subscribe(
console.log,
console.error
);
source$.next('1');
source$.next('2');