如何知道当效果在ngrx组件存储(rxjs流)的效果内完成?



我目前正在实现一个功能,"打开一个对话框"(效果),在对话框打开后,用户点击保存,然后我想关闭对话框。

我做了假的对话和流程的例子。

我还将流分成两个效果:openDialogEffectsaveEffect,以避免"operator-hell";并且代码可读性更强,并且可以重用保存效果。

这个很好。直到我想在保存成功后关闭对话框。问题是如何"上钩"。进入saveEffect管道?

我在这里重现了这个问题:

readonly openDialogEffect = this.effect(($: Observable<any>) =>
$.pipe(
exhaustMap((dialogRef) =>
dialogRef.open().pipe(
tap({
next: () => {
this.saveEffect(); // <----- after that need to close the dialog... but how??
// then: dialogRef.close();
},
})
)
)
)
);
readonly saveEffect = this.effect(($) =>
$.pipe(
exhaustMap(() =>
this.api.save().pipe(
switchMap((res) =>
this.api.updateFoo(res).pipe(
tap({
next: () => {
console.log('after save');
this.toast.success();
},
error: () => {
console.log('in error');
this.toast.error();
},
})
)
)
)
)
)
);

ngrx能够处理纯副作用(不操纵应用程序状态的效果)。虽然你需要从一个效果中调度动作来实现这一点,否则你不能确定它是否成功。

@Component({
// component metadata
})
export class MyComponent implements OnInit {
constructor(
private readonly actions$: Actions,
) {}
ngOnInit() {
this.actions$.pipe(
ofType(someAction),
takeUntil(this.destroy$), // remember to unsubscribe
).subscribe(({payload}) => {
// show toast
// close dialog
});
}
}

你可以创建一个回调并传递给saveEffect通过openDialogEffect:

回调可以是:

  1. 定制rxjs操作符

1。using function callback

函数回调

@Injectable()
export class AppService extends ComponentStore<State> {
readonly openDialogEffect = this.effect<{
// new code
whenSaved: () => void;
dialogRef;
}>((arg$) =>
arg$.pipe(
exhaustMap(({ whenSaved, dialogRef }) =>
dialogRef.open().pipe(
tap({
next: () => {
this.saveEffect({
whenSaved,
});
// then: dialogRef.close();
},
})
)
)
)
);
readonly saveEffect = this.effect<{
// new codes
whenSaved: () => void;
}>((arg$) =>
arg$.pipe(
exhaustMap((arg) =>
this.api.save().pipe(
switchMap((res) =>
this.api.updateFoo(res).pipe(
tap({
next: () => {
console.log('after save');
arg.whenSaved();
this.toast.success();
},
error: () => {
console.log('in error');
this.toast.error();
},
})
)
)
)
)
)
);
constructor(private api: ApiService, private toast: ToastrService) {
super();
this.openDialogEffect(
of({
dialogRef: dialog,
whenSaved: () => {
console.log('saved!!');
},
})
);
}
}

2。使用自定义rxjs操作符

自定义RXJS操作符

@Injectable()
export class AppService extends ComponentStore<State> {
readonly openDialogEffect = this.effect<{
// new code
whenSaved$: () => MonoTypeOperatorFunction<unknown>;
dialogRef;
}>((arg$) =>
arg$.pipe(
exhaustMap(({ whenSaved$, dialogRef }) =>
dialogRef.open().pipe(
tap({
next: () => {
this.saveEffect({
whenSaved$,
});
// then: dialogRef.close();
},
})
)
)
)
);
readonly saveEffect = this.effect<{
// new codes
whenSaved$: () => MonoTypeOperatorFunction<unknown>;
}>((arg$) =>
arg$.pipe(
exhaustMap((arg) =>
this.api.save().pipe(
switchMap((res) =>
this.api.updateFoo(res).pipe(
tap({
next: () => {
console.log('after save');
this.toast.success();
},
error: () => {
console.log('in error');
this.toast.error();
},
}),
arg.whenSaved$()
)
)
)
)
)
);
constructor(private api: ApiService, private toast: ToastrService) {
super();
this.openDialogEffect(
of({
dialogRef: dialog,
whenSaved$: () => {
return function <T>(source: Observable<T>): Observable<T> {
return source.pipe(
tap((isSaved) => console.log('save!', isSaved)),
tap(() => console.log('do some thing...'))
);
};
},
})
);
}
}

最新更新