最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

ngrx/store 之會員篇 Effects, Selector

XAMPP下载 admin 1937浏览 0评论
 ngrx/store 之會員篇 Effects, Selector
今天開始 今天完成

今天目標:完成會員部分的 ngrx/store
複習一下我們的目標

QQ截图20181011155830

 複習一下 [ngrx/store-7] 純函數 (Pure Function), Effects 在 store 中的角色就是要處理有“副作用”的部分,例如跟後端聯繫,讀出寫入 Localstorage 等等,不是純函數的部分,在會員篇的狀態中, Login, Logout, GetUser 都會有“副作用”,所以也都會用到 Effects,

會員篇 – Effects
第一步:建立 src/app/store/effects/user.effects.ts

ng generate class user.effects –spec
第二步:修改 user.effects.ts

import { Injectable } from ‘@angular/core’;
import { Action } from ‘@ngrx/store’;
import { Effect, Actions } from ‘@ngrx/effects’;

import { Observable } from ‘rxjs/Observable’;
import { of } from ‘rxjs/observable/of’;
import { map, switchMap, filter, catchError } from ‘rxjs/operators’;

import { UserService } from ‘../../userrvice/user.service’;
import { UtilsService } from ‘../..rvices/utils.service’;
import { User, Response } from ‘../../models’;
import * as actions from ‘../actions’;

@Injectable()
export class UserEffects {
constructor(
private action$: Actions,
private userService: UserService,
private utils: UtilsService
) { }

@Effect()
loginEffect$: Observable<Action> = this.action$.ofType(actions.LOGIN).pipe(
map((action: actions.LoginAction) => action.payload),
switchMap((user: User) => {
return this.userService.loginServer(user).pipe(
map((res: Response) => {
if (res.success) {
if (user.rememberMe) {
this.utils.writeToken(res.payload);
}
return new actions.LoginSuccessAction(user.username);
} else {
return new actions.LoginFailAction(res.payload);
}
}),
catchError((err) => of(new actions.LoginFailAction(err))),
)
}),
);

@Effect()
logoutEffect$: Observable<Action> = this.action$.ofType(actions.LOGOUT).pipe(
map(() => {
this.utils.removeToken();
return (new actions.LogoutSuccessAction());
})
)

@Effect()
getUserEffect$: Observable<Action> = this.action$.ofType(actions.GETUSER).pipe(
switchMap(() => {
return this.userService.getUserFromServer().pipe(
filter(user => (user !== null)),
map((user: User) => new actions.GetUserSuccessAction(user.username)),
catchError(err => of(new actions.GetUserFailAction(err))),
)
})
)
}
在 constructor() 導入動作 Actions(監聽用),使用者服務 UserService(跟後端連結)跟工具服務 UtilsService (寫入讀出 Localstorage)
Effect 函數使用 this.action$.ofType() “監聽“ 動作 (Action),處理完“副作用“的部分後,最後會輸出 Observable<Action> 另外的動作
loginEffect$ 監聽 “LOGIN” 的動作,一聽到這個動作,先從動作的payload取出資料,之前我們在定義
export class LoginAction implements Action {
readonly type = LOGIN;

constructor(public payload: User) { }
}
時,已經定義了 payload是 User 型態,接著用 switchMap 來使用 UserService,請回憶一下[ngrx/store -5] 高階 (High Order) Observable,因為 UserService.loginServer() 本身也是 Observable,我們需要用到高階運算子,如果登入成功的話,寫入從後端傳回的 token,分派一個成功的動作LoginSuccessAction 交給 Reducer,前面定義過的 Reducer,就會產生新的狀態

//…省略
switch (action.type) {
case actions.LOGOUT:
return initialState;
case actions.LOGIN_SUCCESS:
case actions.GETUSER_SUCCESS:
return { …state, currentUser: action.payload, isLogin: true };
default:
return state
}
//…
logoutEffect$ 監聽 “LOGOUT” 的動作,簡單的做清除 token
getUserEffect$ 監聽 “GETUSER” 的動作,一樣使用使用者服務,從後端取回使用者名稱,在依後端回覆的狀況,產生GetUserSuccessAction 或是 GetUserFailAction 給 Reducer
第三步:修改 src/app/store/effects/index.ts

 import { UserEffects } from ‘./user.effects’;
export const effects: any[] = [UserEffects];
export * from ‘./user.effects’;
放在 effects 的陣列中,這樣 app.module.ts 就會註冊這個 effects

會員篇 – Selector
有人形容 store 就像前端的資料庫,如果狀態樹是表格 (Table) 的話,那選擇器(Selector) 就像是事先寫好的查詢(Query)一樣,複雜的 Selector 可能會跨不同的狀態樹枝,就像資料庫的 Join 般連結起使用者想要得到的資料,我們以後會看到
第一步: 建立 src/app/storelectorslectors.ts

ng generate class selectors –spec
第二步:修改 selectors.ts

import { createSelector } from ‘reselect’;

import * as fromReducer from ‘../reducers’;
import * as user from ‘../reducers/user.reducers’;

// for selector
export const getUserState = (state: fromReducer.State) => state.user;                        // point to users state subtree
export const getIsLogin = createSelector(getUserState, user.getIsLogin);
export const getCurrentUser = createSelector(getUserState, user.getCurrentUser);
導入 createSelector 函數,詳情請參考官方文件,前面的參數指向狀態樹的哪一個部分,這個例子 getUserState 指向狀態樹的 state.user 樹枝(在 store/reducer/index.ts 中),後面的參數傳回從這個樹枝傳回的資料, user.getIsLogin 跟 user.getCurrentUser (這個在 user.reducer.ts 中定義)

因為我們的 selectors 相對單純,我們就先用一個檔案就好,以後複雜時,再來擴充
第三步:修改 src/app/storelectors/index.ts

export * from ‘.lectors’;
下次我們要將元件改版,從原來使用服務的地方,改成使用 ngrx/store

 

转载请注明:XAMPP中文组官网 » ngrx/store 之會員篇 Effects, Selector

您必须 登录 才能发表评论!