简体   繁体   English

如何调度取决于 Http 方法的操作?

[英]How to Dispatch action which depends on Http method?

I am using NGXS for state management in my angular application.我在我的 angular 应用程序中使用NGXS进行 state 管理。

Which one is a good practice?哪一个是好的做法?

  1. First HTTP call then Dispatch action in it's subscription?首先 HTTP 调用然后在它的订阅中调度操作?
  2. First Dispatch action and then HTTP call in it's pipe method?首先调度操作,然后 HTTP 调用它的 pipe 方法?

For example, what is the process of user login using state management?比如用户使用state管理登录的流程是怎样的? Here, I have to make an HTTP call & then I have to do something depending on the response I get from the HTTP response.在这里,我必须进行 HTTP 调用,然后我必须根据从 HTTP 响应中得到的响应来做一些事情。

Which one is good practice & why?哪一个是好的做法,为什么?

Also, please share example.另外,请分享示例。 Thanks in advance.提前致谢。

Typical flow would look like so that LoginIn action, triggers HTTP request authService.loginIn() to validate credentials, successful response triggers LoginSuccess , that action sets credentials to service/storage etc (isLoggedIn = true), components/services listening to state change react (or use authService to store logIn state);典型的流程看起来像这样LoginIn操作,触发 HTTP 请求authService.loginIn()以验证凭据,成功响应触发LoginSuccess ,该操作将凭据设置为服务/存储等(isLoggedIn = true),组件/服务监听 Z9ED39E2EA931586B6A985A6942EF573E 更改反应(或使用 authService 存储登录状态);

LoginComponent.ts登录组件.ts

  login() {
    console.log(this.loginFrom.valid);
    console.log(this.loginFrom.value);
    this.store.dispatch(new Login(this.loginFrom.value));
  }

AuthService.ts身份验证服务.ts

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  private baseUrl = environment.apiUrl;
  constructor(private _http: HttpClient) {}

  loginIn(user: User) {
    let { email, password } = user;
    return this._http.post<User>(`${this.baseUrl}/login`, { email, password });
  }
}

Effects.ts效果.ts

@Injectable()
export class AuthEffects {
  @Effect()
  LoginIn: Observable<any> = this.actions.pipe(
    ofType(AuthActionTypes.LOGIN),
    map((action: Login) => action.payload),
    switchMap((payload) => {
      return this.authService.loginIn(payload).pipe(
        map((user: any) => {
          return new LoginSuccess({ token: user.token, email: payload.email });
        }),
        catchError((error) => {
          return of(new LoginFailure({ error }));
        })
      );
    })
  );
  @Effect({ dispatch: false })
  LoginSuccess: Observable<any> = this.actions.pipe(
    ofType(AuthActionTypes.LOGIN_SUCCESS),
    tap((user) => {
      localStorage.setItem('token', user.payload.token);
      this.router.navigate(['home']);
    })
  );

  @Effect({ dispatch: false })
  LogInFailure: Observable<any> = this.actions.pipe(
    ofType(AuthActionTypes.LOGIN_ERROR)
  );

  @Effect({ dispatch: false })
  LogOut: Observable<any> = this.actions.pipe(
    ofType(AuthActionTypes.LOGOUT),
    tap(() => {
      localStorage.removeItem('token');
      this.router.navigate(['login']);
    })
  );

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

Actions.ts动作.ts

export enum AuthActionTypes {
  LOGIN = '[Auth] Login',
  LOGIN_SUCCESS = '[Auth] SUCCESS',
  LOGIN_ERROR = '[Auth] LOGIN_ERROR',
  LOGOUT = '[Auth] Logout',
}

export class Login implements Action {
  type = AuthActionTypes.LOGIN;
  constructor(public payload: any) {}
}

export class LoginSuccess implements Action {
  type = AuthActionTypes.LOGIN_SUCCESS;
  constructor(public payload: any) {}
}

export class LoginFailure implements Action {
  type = AuthActionTypes.LOGIN_ERROR;
  constructor(public payload: any) {}
}

export class Logout implements Action {
  type = AuthActionTypes.LOGOUT;
}

export type All = Login | LoginSuccess | LoginFailure | Logout;

Reducer.ts减速器.ts

export interface IState {
  isAuthenticated: boolean;
  user: User | null;
  error: any;
}

export const initialState = {
  isAuthenticated: false,
  user: null,
  error: null,
};

export function reducer(state = initialState, action: any): IState {
  switch (action.type) {
    case AuthActionTypes.LOGIN_SUCCESS: {
      return {
        ...state,
        isAuthenticated: true,
        user: {
          email: action.payload.email,
          password: action.payload.password,
        },
        error: null,
      };
    }

    case AuthActionTypes.LOGIN_ERROR: {
      return {
        ...state,
        error: 'Invalid User/Password',
      };
    }

    case AuthActionTypes.LOGOUT: {
      return initialState;
    }

    default: {
      return state;
    }
  }
}

HomeComponent.ts主页组件.ts

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  state$: Observable<any>;
  isAuthenticated: boolean;
  error: any;
  user: User;
  constructor(private store: Store<IAppState>) {
    this.state$ = this.store.select((state) => state.auth);
  }

  ngOnInit() {
    this.state$.subscribe((r: IState) => {
      this.user = r.user;
      this.error = r.error;
      this.isAuthenticated = r.isAuthenticated;
    });
  }

  logout() {
    this.store.dispatch(new Logout());
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM