保持错误信息和外部可观察性



为了确保错误不会完成外部可观察量,我采用的常见 rxjs 效果模式是:

public saySomething$: Observable<Action> = createEffect(() => {
return this.actions.pipe(
ofType<AppActions.SaySomething>(AppActions.SAY_SOMETHING),
// Switch to the result of the inner observable.
switchMap((action) => {
// This service could fail.
return this.service.saySomething(action.payload).pipe(
// Return `null` to keep the outer observable alive!
catchError((error) => {
// What can I do with error here?
return of(null);
})
)
}),
// The result could be null because something could go wrong.
tap((result: Result | null) => {
if (result) {
// Do something with the result!
}
}),
// Update the store state.
map((result: Result | null) => {
if (result) {
return new AppActions.SaySomethingSuccess(result);
}
// It would be nice if I had access the **error** here. 
return new AppActions.SaySomethingFail();
}));
});

请注意,我在内部可观察量上使用catchError,以便在底层网络调用失败时保持外部可观察量处于活动状态(service.saySomething(action.payload)(:

catchError((error) => {
// What can I do with error here?
return of(null);
})

随后的tapmap运算符通过允许null在其签名中容纳这一点,即(result: Result | null).但是,我丢失了错误信息。最终,当最终map方法返回时new AppActions.SaySomethingFail();我丢失了有关错误的任何信息。

如何在整个管道中保留错误信息,而不是在捕获时丢失错误信息?

正如评论中所建议的,您应该使用类型保护功能

不幸的是,我无法在代码段中运行打字稿,所以我评论了类型

const { of, throwError, operators: {
switchMap,
tap,
map,
catchError
}
} = rxjs;
const actions = of({payload: 'data'});
const service = {
saySomething: () => throwError(new Error('test'))
}
const AppActions = {
}
AppActions.SaySomethingSuccess = function () {
}
AppActions.SaySomethingFail = function() {
}
/* Type guard */
function isError(value/*: Result | Error*/)/* value is Error*/ {
return value instanceof Error;
}
const observable = actions.pipe(
switchMap((action) => {

return service.saySomething(action.payload).pipe(
catchError((error) => {
return of(error);
})
)
}),
tap((result/*: Result | Error*/) => {
if (isError(result)) {
console.log('tap error')
return;
}

console.log('tap result');
}),
map((result/*: Result | Error*/) => {
if (isError(result)) {
console.log('map error')
return new AppActions.SaySomethingFail();
}

console.log('map result');
return new AppActions.SaySomethingSuccess(result);
}));

observable.subscribe(_ => {
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.js"></script>

我不会尝试在整个管道中保留错误信息。相反,你应该把你的成功管道(tapmap(与你的错误管道(catchError(分开,将所有运算符添加到他们应该实际使用的结果的可观察量中,即你的内在可观察量。

public saySomething$: Observable<Action> = createEffect(() => {
return this.actions.pipe(
ofType<AppActions.SaySomething>(AppActions.SAY_SOMETHING),
switchMap((action) => this.service.saySomething(action.payload).pipe(
tap((result: Result) => {
// Do something with the result!
}),
// Update the store state.
map((result: Result) => {
return new AppActions.SaySomethingSuccess(result);
}),
catchError((error) => {
// I can access the **error** here. 
return of(new AppActions.SaySomethingFail());
})
)),     
);
});

这样,tapmap只会在this.service.saySomething的成功结果上执行。将所有错误副作用和错误映射移到catchError中。

相关内容

  • 没有找到相关文章

最新更新