[英]How to catch error and continue executing a sequence in RxJs?
我有一个要解析的项目列表,但其中一个项目的解析可能会失败。
捕获错误但继续执行序列的“Rx-Way”是什么
代码示例:
var observable = Rx.Observable.from([0,1,2,3,4,5]).map( function(value){ if(value == 3){ throw new Error("Value cannot be 3"); } return value; }); observable.subscribe( function(value){ console.log("onNext " + value); }, function(error){ console.log("Error: " + error.message); }, function(){ console.log("Completed;"); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
我想以非 Rx 方式做的事情:
var items = [0,1,2,3,4,5]; for (var item in items){ try{ if(item == 3){ throw new Error("Value cannot be 3"); } console.log(item); }catch(error){ console.log("Error: " + error.message); } }
我建议你改用flatMap
(现在mergeMap
版本 5 中的 mergeMap),如果你不关心它们,它会让你折叠错误。 实际上,您将创建一个内部 Observable,如果发生错误,它可以被吞下。 这种方法的优点是你可以将操作符链接在一起,如果管道中的任何地方发生错误,它都会自动转发到 catch 块。
const {from, iif, throwError, of, EMPTY} = rxjs; const {map, flatMap, catchError} = rxjs.operators; // A helper method to let us create arbitrary operators const {pipe} = rxjs; // Create an operator that will catch and squash errors // This returns a function of the shape of Observable<T> => Observable<R> const mapAndContinueOnError = pipe( //This will get skipped if upstream throws an error map(v => v * 2), catchError(err => { console.log("Caught Error, continuing") //Return an empty Observable which gets collapsed in the output return EMPTY; }) ) const observable = from([0, 1, 2, 3, 4, 5]).pipe( flatMap((value) => iif(() => value != 3, of(value), throwError(new Error("Value cannot be 3")) ).pipe(mapAndContinueOnError) ) ); observable.subscribe( (value) => console.log("onNext " + value), (error) => console.log("Error: " + error.message), () => console.log("Completed!") );
<script src="https://unpkg.com/rxjs@7.0.0/dist/bundles/rxjs.umd.min.js"></script>
您需要切换到一个新的一次性流,如果其中发生错误将被安全处理,并保持原始流处于活动状态:
Rx.Observable.from([0,1,2,3,4,5]) .switchMap(value => { // This is the disposable stream! // Errors can safely occur in here without killing the original stream return Rx.Observable.of(value) .map(value => { if (value === 3) { throw new Error('Value cannot be 3'); } return value; }) .catch(error => { // You can do some fancy stuff here with errors if you like // Below we are just returning the error object to the outer stream return Rx.Observable.of(error); }); }) .map(value => { if (value instanceof Error) { // Maybe do some error handling here return `Error: ${value.message}`; } return value; }) .subscribe( (x => console.log('Success', x)), (x => console.log('Error', x)), (() => console.log('Complete')) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>
这篇博文中有关此技术的更多信息: The Quest for Meatballs: Continue RxJS Streams When Errors Occurs
为了防止你的endlessObservable$
死亡,你可以将你的failingObservable$
放在一个高阶映射操作符(例如switchMap
、 concatMap
、 exhaustMap
...)中,并通过用一个empty()
observable终止内部流而不返回任何值来吞下错误.
使用 RxJS 6:
endlessObservable$
.pipe(
switchMap(() => failingObservable$
.pipe(
catchError((err) => {
console.error(err);
return EMPTY;
})
)
)
);
如果您不想或无法访问导致错误的内部可观察对象,您可以执行以下操作:
使用 RxJS 7:
const numbers$ = new Subject();
numbers$
.pipe(
tap(value => {
if (value === 3) {
throw new Error('Value cannot be 3');
}
}),
tap(value => {
console.log('Value:', value);
}),
catchError((err, caught) => {
console.log('Error:', err.message);
return caught;
})
)
.subscribe();
for (let n = 1; n <= 10; n++) {
numbers$.next(n);
}
这里有趣的是可以返回的 catchError 运算符中的“捕获”参数。 https://rxjs.dev/api/operators/catchError
它仅在源 observable 为 Hot 时有效。
就我而言,我使用 redux-observable 并且我想要一种方法来在一个地方处理我的错误。
我想出了这个:
const allEpics = combineEpics(
// all my epics
);
export const rootEpic = (action$, state$, dependencies) => {
return allEpics(action$, state$, dependencies).pipe(
catchError((err, caught) => {
if (err instanceof MyError) {
return concat(of(displayAlert(err.message)), caught);
}
throw err;
})
);
};
如果我的任何史诗抛出“MyError”异常,它将被捕获并调度另一个动作。
您实际上可以在map函数中使用try/catch来处理错误。 这是代码片段
var source = Rx.Observable.from([0, 1, 2, 3, 4, 5]) .map( function(value) { try { if (value === 3) { throw new Error("Value cannot be 3"); } return value; } catch (error) { console.log('I caught an error'); return undefined; } }) .filter(function(x) { return x !== undefined; }); source.subscribe( function(value) { console.log("onNext " + value); }, function(error) { console.log("Error: " + error.message); }, function() { console.log("Completed!"); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.