我开始研究ngrx / Store,并且面临以下问题。
从我的UI组件中,我需要执行对远程rest API的调用,这可能会花费一些时间来执行。我想管理向用户显示标准loading-spinner的等待时间。
我习惯用看起来像这样的代码来管理这种情况
let loading = this.loadingCtrl.create({
content: 'Please wait while we load stuff'
});
loading.present();
this.longRunningService.doHeavyWork()
.subscribe(
(result) => {
// manage result;
},
(err) => console.log(err),
() => loading.dismiss()
);
上面的代码片段(对于我的问题)的关键点是,当longRunningService
完成doHeavyWork
逻辑时(即,当Observable完成时),将取消加载微调器。
现在,我想重构此代码并使用ngrx / Store 调度机制。
我的问题是loading.dismiss()
在使用ngrx / Store dispatch
机制时如何管理逻辑。换句话说,当使用ngrx / Store dispatch Action机制时,我不知道如何关闭loading-spinner(一旦已经从后端rest API接收到结果)。
任何建议都非常感谢
您需要添加ngrx / effects库来处理诸如“ longRunningService”之类的副作用
我从ngrx的官方示例中学到了这一点。我建议您看看https://github.com/ngrx/example-app
以下代码基于example-app并处理了加载内容,请检查一下。
我假设您正在编写ionic v2应用程序?因为LoadingController ..
动作:
export const LOAD_STUFF = "LOAD_STUFF";
export const LOAD_STUFF_SUCCESS = "LOAD_STUFF_SUCCESS";
export const LOAD_STUFF_FAIL = "LOAD_STUFF_FAIL";
@Injectable()
export class StuffActions{
loadStuff() : Action {
return {
type: LOAD_STUFF
};
}
loadStuffSuccess(stuff : any []) : Action {
return {
type: LOAD_STUFF_SUCCESS,
payload: stuff
};
}
}
减速器
export interface State {
entities: [];
loading : boolean;
complete : boolean;
}
const initalState : State = {
entities: [];
loading : false;
complete : false;
};
export function reducer(state = initalState, action) : State {
switch (action.type) {
case LOAD_STUFF:
return Object.assign({}, state, {
loading: true,
complete: false
});
case LOAD_STUFF_SUCCESS:
return {
complete: true,
loading: false,
entities : action.payload
};
default:
return state;
}
}
// SELECTORS
export const getLoading = (state: State) => state.loading;
export const getComplete = (state: State) => state.complete;
export const getEntities = (state: State) => state.stuff;
效果
@Injectable()
export class EnvioEffects {
constructor(private actions$: Actions, private _stuffActions : StuffActions, private _longRunningService: LongRunningService ){}
@Effect() loadStuff: Observable<Action> = this.actions$
.ofType(LOAD_STUFF)
.switchMap(() => this._longRunningService.getStuff())
.map( stuff => this._stuffActions.loadStuffSuccess(stuff));
}
选择器索引。对于选择器,我使用https://github.com/reactjs/reselect
import * as fromStuff from "./stuff";
import {createSelector} from "reselect";
import {ActionReducer, combineReducers, Action} from "@ngrx/store";
export interface State {
stuff: fromStuff.State
}
const reducers = {
stuff: fromStuff.reducer
};
export const reducer: ActionReducer<State> = combineReducers(reducers);
export const rootReducer = (state: State, action: Action) => {
return reducer(state, action);
};
export const getStuffEntities = createSelector(getOriginState, fromStuff.getEntities);
export const getStuffLoading = createSelector(getOriginState, fromOrigin.getLoading);
export const getStuffComplete = createSelector(getOriginState, fromOrigin.getComplete);
页
import * as fromRoot from "../../reducers/index";
@Component({
selector: 'stuff',
templateUrl: 'stuff.html'
})
export class StuffPage implements OnDestroy {
destroy$: Subject<any> = new Subject();
constructor(public navCtrl: NavController,
public loadingCtrl: LoadingController,
private _store: Store<fromRoot.State>,
private _stuffActions: StuffActions) {
}
ionViewDidLoad() {
// HERE I SHOW THE LOADING ANIMATION UNTIL THE LONG RUNNING SERVICE COMPLETE
this._store.select(fromRoot.getStuffLoading)
.takeUntil(this.destroy$)
.filter(isloading => isloading)
.map(() => this.createLoader())
.do(loading => loading.present())
.delayWhen(loading => this._store.select(fromRoot.getStuffComplete).filter(complete => complete))
.map(loading => loading.dismiss())
.subscribe();
// LOAD THE STUFF
this._store.dispatch(this._stuffActions.loadStuff());
}
createLoader(): Loading {
return this.loadingCtrl.create({
content: "Loading stuff"
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.unsubscribe();
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句