NGRX 效果 - 为具有 {dispatch: false} 的效果分派动作是不好的做法吗?

NGRX effects - is it bad practice to dispatch actions for effects that have {dispatch: false}?

我有一个可能会或可能不会发送操作的效果:

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

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

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

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

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

此外,您还在效果中手动订阅:这也是一种不好的做法!使用此代码,您没有扁平化运算符所拥有的控制级别(例如,取消之前的请求)。

作为一般指南,假设您遇到这种情况:

map(action => condition ? otherAction : null)

这显然行不通,因为 null 不是有效的操作。

因此,将 map 更改为 switchMap(或其他扁平化运算符)并按如下方式修改您的代码:

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

...

switchMap(action => condition ? of(otherAction) : EMPTY)

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


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

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