保持错误信息和外部 observable 活动
Keeping error information and the outer observable alive
为了确保错误不会完成 outer observable,我采用的常见 rxjs effects 模式是:
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();
}));
});
请注意,我在 inner observable 上使用 catchError
以保持 outer observable 在底层网络时保持活动状态呼叫失败(service.saySomething(action.payload)
):
catchError((error) => {
// What can I do with error here?
return of(null);
})
随后的 tap
和 map
运算符通过允许 null
,即 (result: Result | null)
在其签名中容纳这一点。但是,我丢失了错误信息。最终当最终 map
方法 returns new AppActions.SaySomethingFail();
我丢失了关于错误的任何信息。
如何在整个管道中保留错误信息而不是在它被捕获时丢失它?
根据评论中的建议,您应该使用 Type guard function
不幸的是,我无法在片段中 运行 打字稿,所以我评论了类型
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>
我不会尝试在整个管道中保留错误信息。相反,你应该将你的成功管道(tap
、map
)与你的错误管道(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());
})
)),
);
});
这样 tap
和 map
只会在 this.service.saySomething
的成功结果上执行。将所有错误副作用和错误映射移动到 catchError
.
为了确保错误不会完成 outer observable,我采用的常见 rxjs effects 模式是:
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();
}));
});
请注意,我在 inner observable 上使用 catchError
以保持 outer observable 在底层网络时保持活动状态呼叫失败(service.saySomething(action.payload)
):
catchError((error) => {
// What can I do with error here?
return of(null);
})
随后的 tap
和 map
运算符通过允许 null
,即 (result: Result | null)
在其签名中容纳这一点。但是,我丢失了错误信息。最终当最终 map
方法 returns new AppActions.SaySomethingFail();
我丢失了关于错误的任何信息。
如何在整个管道中保留错误信息而不是在它被捕获时丢失它?
根据评论中的建议,您应该使用 Type guard function
不幸的是,我无法在片段中 运行 打字稿,所以我评论了类型
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>
我不会尝试在整个管道中保留错误信息。相反,你应该将你的成功管道(tap
、map
)与你的错误管道(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());
})
)),
);
});
这样 tap
和 map
只会在 this.service.saySomething
的成功结果上执行。将所有错误副作用和错误映射移动到 catchError
.