Rxjs 错误后仅触发一次订阅
我是rxjs的新手,我正试图弄清楚下面的代码中发生了什么 事实上,为了说明这个想法,我准备了两个简单的承诺(resolvePromise和rejectPromise),一个解决承诺,另一个拒绝。 “Subject”实例用于触发这两个承诺(通过mergeMap和forkJoin管道)。最后,添加了两条单独的指令(source$.next('xxx'),希望触发订阅两次 但最后,只有第一个“source$.next('1')”触发订阅,而下一个“source$.next('2')”似乎什么也不做 我猜这种行为是由拒绝承诺造成的,它字面上是“抛出异常”。 但是我想知道如何修复这段代码,这样第二个“source$.next('2')”也会触发订阅 非常感谢Rxjs 错误后仅触发一次订阅,rxjs,Rxjs,我是rxjs的新手,我正试图弄清楚下面的代码中发生了什么 事实上,为了说明这个想法,我准备了两个简单的承诺(resolvePromise和rejectPromise),一个解决承诺,另一个拒绝。 “Subject”实例用于触发这两个承诺(通过mergeMap和forkJoin管道)。最后,添加了两条单独的指令(source$.next('xxx'),希望触发订阅两次 但最后,只有第一个“source$.next('1')”触发订阅,而下一个“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');
更新 根据Andrei Gă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);
拒绝承诺,字面意思是“抛出一个例外”
从RxJS内部处理承诺的方式来看,我认为你是对的:
promise.then(
(值)=>{
如果(!subscriber.closed){
订户。下一个(值);
subscriber.complete();
}
},
(err:any)=>subscriber.error(err)/!
)
同样值得一提的是,正如您从上面的代码片段中看到的,一旦承诺第一次得到解决,解决值和完成
通知将被传递
complete
部分对于forkJoin
操作员非常重要
forkJoin
订阅所有提供的可观察对象,并等待直到所有操作完成。只有当观测值至少发射一次时,它才会发送一个值为的数组
当一个被观察者发出一个错误
通知时,forkJoin
将立即在链的更远处发送该错误
通知
以下是我的方法:
source$
.pipe(合并映射(val=>{
返回叉连接([
承诺(val),
from(拒绝承诺(val)).pipe(catchError(err=>of(err)))
]);
}))
.订阅(
console.log,
控制台错误
);
我们使用的是来自的
,这样我们可以尽早截获承诺错误,这允许我们使用捕获错误
并使用一个可观察的对象,该对象将发送一个值,然后完成
通知(of(err)
)。您需要通过重试
或重复
重新订阅
从'rxjs'导入{of,forkJoin,Subject};
从“rxjs/operators”导入{mergeMap};
const resolvePromise=val=>
新承诺(resolve=>resolve(`resolve value:${val}`));
常量拒绝承诺=错误=>
Promise.reject(`reject error:${err}`);
const source$=新主题();
source$.pipe(
合并映射(val=>forkJoin([
承诺(val),
拒绝承诺(val)
])),
catchError(()=>空),
重复(),
).订阅(
console.log,
控制台错误
);
来源$.next('1');
来源$.next('2');
嗨,安德烈,谢谢你的建议。你的建议对我来说确实有效。根据您的想法,我想知道它是否也可以作为这样做的解决方案:(对不起注释中的代码样式)source$.pipe(mergeMap(val=>{returnforkjoin([resolvespromise(val),rejectPromise(val)]).pipe(catchError(err=>{console.error(err);returnempty()};})订阅(console.log);我的意思是,我们将错误处理放在forkJoin之后的catchError函数中。这样我们就不需要签入订阅,无论我们是否得到错误或正常结果。如果source$是主题和/或只要未完成,我认为这应该可以正常工作。嗨,satanTime,谢谢你的建议。“重试”会多次尝试解决forkJoin问题,但是,如果其中一个承诺/可观察项始终失败,例如,业务规则检查失败,那么无论我们重试多少次,结果都将保持不变。啊哈,我明白了,您的代码中是否使用了主题
?我已将示例更新为使用repeat
。