NGRX 效果 - 为具有 {dispatch: false} 的效果调度操作是一种不好的做法吗?

mil*_*eow 3 ngrx-effects

我有一个效果,可能会也可能不会发送动作:

handleMainAccount$ = createEffect(() => {
    return this._actions$.pipe(
      ofType(setUserDetails),
      tap( (details) => {
          if (details?.mainAccount) {
            const fakeData = { foo: 'bar'};
            this._accountHttpSvc.updateAccount(fakeData).pipe(
              take(1), // so we don't have to unsub
              map((res) => {
                this._userStore.dispatch(setMainAccount({fakeData}));
              }),
            ).subscribe();
          }

          // else 
          // we are not dispatching any action

      })
    );
  } , { dispatch: false } ); // setting as false, because we may or may not dispatch an action
Run Code Online (Sandbox Code Playgroud)

我将调度设置为 false,因为有时此效果可能不会调度操作。这是不好的做法吗?如果有的话会有什么负面影响?

Mic*_*ven 5

恕我直言,这是一个不好的做法。我将效果分为两类:

  1. 发出动作的效果
  2. 没有的效果

你的有点“两者”。如果需求发生变化,测试和管理就会变得更加困难。

另外,您在效果内手动订阅:这也是一个不好的做法!使用此代码,您无法获得展平运算符所具有的控制级别(例如,取消先前的请求)。

作为一般指南,假设您遇到以下情况:

map(action => condition ? otherAction : null)
Run Code Online (Sandbox Code Playgroud)

这显然不起作用,因为这null不是有效的操作。

因此,更改map为switchMap(或另一个展平运算符)并按如下方式修改代码:

import { switchMap, of, EMPTY } from 'rxjs';

...

switchMap(action => condition ? of(otherAction) : EMPTY)
Run Code Online (Sandbox Code Playgroud)

在您的场景中,您希望有条件地执行请求。它会是这样的而不是你的tap:


switchMap(condition => {
  if (!condition) {
    return EMPTY
  }
  
  return this.service.update(...).pipe(
    take(1),
    map(x => yourAction())
  )
})

Run Code Online (Sandbox Code Playgroud)

显然,您可以使用任何其他展平运算符来代替switchMap。对于switchMap并发请求,将取消前一个请求,它们mergeMap将被并行处理,concatMap它们将排队,exhaustMap如果前一个调用尚未完成,则第二个请求将不起作用。