动作会激活,但在使用带有响应的效果时会冻结

问题描述 投票:0回答:1

这是一个具体问题,没有可以在网上轻松找到合适答案的问题。

/ *背景故事-可跳过* /

我最近创建了一个新项目,旨在遵循Redux Patterns,同时还使用Google Firestore作为我选择的数据存储。

因为这是一个新应用程序,它相对来说是空的-但是,我认为首先通过身份验证将信息添加到数据存储中是合适的。

过去,我曾使用一项服务登录并处理身份验证。但是,这次我正在使用NgRx。

我已经设法正确设置商店,并且在使用选择器,操作和简化器时,它可以按预期工作。但是-问题出在需要效果时,例如通过Google Firestore评估信息时。

/ *背景故事结束* /

问题

问题是,尝试登录时会触发适当的身份验证操作,但是存储被冻结,并且在遇到致命错误后不会更新。

这样,我们将永远不会收到用户信息,并且下图中显示的错误使商店停止运转。

enter image description here

上面的错误是在调度操作以登录后发生的。触发登录事件,并从服务器收到状态为200的响应。它在“网络”选项卡中返回所需的信息。纯粹在事物的存储方面,事物会失败。

我想知道为什么。

The Project

我对该项目具有以下设置。

auth.actions.ts

export const getAuthState = createAction('[Auth] Get Auth State');

export const login = createAction('[Auth] Login', props<{ credentials: Credentials }>());
export const loginSuccess = createAction('[Auth] Login Successful', props<{ user: UserCredential }>());
export const loginFailure = createAction('[Auth] Login Failed', props<{ error: any }>());
export const loginFinalize = createAction('[Auth] Login Finalized');

auth.reducer.ts

export interface AuthState {
  authenticated: boolean;
  authenticationRequestSent: boolean;
  authenticationResponseReceived: boolean;
  error: string;
}

const initialState: AuthState = {
  authenticated: false,
  authenticationRequestSent: false,
  authenticationResponseReceived: false,
  error: null
};

const authReducer = createReducer(initialState,
  on(authActions.getAuthState, state => {
    return {
      ...state,
    };
  }),
  on(authActions.login, state => {
    return {
      ...state,
      authenticationRequestSent: true
    }
  }),
  on(authActions.loginSuccess, state => {
    return {
      ...state,
      authenticationResponseReceived: true
    }
  }),
  on(authActions.loginFinalize, state => {
    return {
      ...state,
      authenticationRequestSent: false,
      authenticationResponseReceived: false
    }
  })
);

export function AuthReducer(state = initialState, action: Action) {
  return authReducer(state, action);
}

auth.effects.ts

@Injectable()
export class AuthEffects {
  login$: Observable<Action> = createEffect<any, any, any, any>(() =>
    this.actions$.pipe(
      ofType(authActions.login),
      switchMap(action =>
        this.authService.logIn(action.credentials).pipe(
          switchMap((userResponse: UserCredential) => from([
            authActions.loginSuccess({user: userResponse}),
            authActions.loginFinalize()
          ])),
          catchError(error => from([
            authActions.loginFailure({error}),
            authActions.loginFinalize()
          ]))
        )
      )
    )
  );

  constructor(
    private actions$: Actions,
    private authService: AuthService
  ) {
  }
}

auth.service.ts

constructor(private firebaseAuth: AngularFireAuth
  ) {
  }

  logIn(credentials: Credentials) {
    const login = new BehaviorSubject(null);
    const login$ = login.asObservable();

    this.firebaseAuth.auth.signInWithEmailAndPassword(credentials.email, credentials.password)
      .then(response => {
        login.next(response);
      }, errorData => {
        login.error(errorData);
      });
    return login$;
  }

app.module.ts

imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebaseConfig),
    AngularFirestoreModule, // firestore
    AngularFireAuthModule, // auth
    AngularFireStorageModule, // storage
    StoreModule.forRoot(reducers),
    EffectsModule.forRoot([AuthEffects]),
    StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: environment.production, // Restrict extension to log-only mode
    }),
  ],

概述

  1. 单击按钮后将分派登录操作
  2. 登录操作处于登录状态,并将其请求发送到服务器
  3. 收到正确的回复以及用户信息
  4. 已分派“登录成功”和“登录完成”操作,但是它们实际上并未更改存储状态,因为它们遇到致命错误,有效地“冻结”了存储。
  5. 同样,我们的登录虽然成功,但从未如此注册,并且用户未更新。

尝试过的内容/有用的信息

如果我从登录成功中删除了道具并且没有通过用户,则代码会运行-但显然这是没有用的,因为我无法将所需的信息实际传递回商店。

angular google-cloud-firestore ngrx ngrx-effects
1个回答
0
投票

我将其重构如下:

对于状态-

export interface AuthState {
  authenticated: boolean;
  error: string;
  user: UserCredential;
}

const initialState: AuthState = {
  authenticated: false,
  error: null,
  user: null
};

为了效果-

login$: Observable<Action> = createEffect<any, any, any, any>(() =>
    this.actions$.pipe(
      ofType(authActions.login),
      switchMap(action =>
        this.authService.logIn(action.credentials).pipe(
          map((userResponse: UserCredential) => authActions.loginSuccess({user: userResponse}))
          catchError(error => authActions.loginFailure({error}),
        )
      )
    )

对于减速器-

on(authActions.loginSuccess, (state, { user })  => {
  return {
    ...state,
    authenticated: true,
    user: user,
    error: null
  }
});

on(authActions.loginError, (state, { error })  => {
  return {
    ...state,
    authenticated: false,
    user: null,
    error: error
  }
});
© www.soinside.com 2019 - 2024. All rights reserved.