ngrx商店-如何在UI中管理可能会持续很长时间的操作

皮奇

我开始研究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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章