无首次加载数据

时间:2019-04-26 14:27:53

标签: angular6 ngrx ngrx-store ngrx-effects

我是NgRx的新手,并尝试使用Effects和http请求检索和缓存分页的表数据。 但是在任何第一次页面加载(如果尚未缓存页面)时,我都会得到一个空页面,即使我对状态对象进行console.log,也能看到里面的数据吗? 当我转到上一页时,数据在那里,所以我猜测异步世界中的某件事我做错了,但无法弄清楚什么:/

这是我的初始化位置 component.ts

  ngAfterViewInit() {

    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);

    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
        startWith({}),
        switchMap(() => {
          this.isLoadingResults = true;

          this.store.dispatch(new ListLoad(this.getQueryParams()));

          return this.store.pipe(select('list'));
         }),
        map((state: State) => {
          this.isLoadingResults = false;
          this.resultsLength = state.totalRecords;

          return this.cacheKey in state.data ? state.data[this.cacheKey] : [];
        }),
        catchError((err) => {
          this.isLoadingResults = false;
          this.resultsLength = 0;

          return observableOf([]);
        })
      )
      .subscribe((data: any[]) => {
        return this.data = data
      });
  }

这是我的效果定义 effects.ts

@Effect()
loadData = this.actions$.pipe(
    ofType(actions.actionTypes.ListLoad),
    mergeMap((action: actions.actionTypes.ListLoadSuccess) => this.service.getAll(action.payload).pipe(
        map(
            response => {
                let apiResponse = new ApiResponse(response);
                let cacheKey = JSON.stringify(action.payload);

                return apiResponse.isSuccess ?
                    new actions.ListLoadSuccess({ key: cacheKey, data: apiResponse.data }) :
                    new actions.ListLoadFailed(`code: ${apiResponse.status.error_code}; message: ${apiResponse.status.error_message}`);
            }
        ),
        catchError(err => observableOf(new actions.ListLoadFailed(err)))
    ))
)

除此之外,如果NgRx存储中存在包含数据的页面,我想取消http请求

1 个答案:

答案 0 :(得分:0)

我能够解决它。问题是我正在通过添加新属性来更新作为对象的商店的属性。存储不会发出片段更新的事件,因此不会触发Select订阅。我介绍了另一个用于加载状态的布尔参数,该参数用于侦听更改,如果加载为false(加载页面),则选择所需的片段。 我还为页面缓存添加了额外的代码

component.ts

  ngOnInit() {

    this.isLoadingResults$ = this.store.pipe(
      select(state => state.stateFragment.isListLoading),
      takeWhile(() => this.componentActive) //unsubscribe
    );

    this.store.dispatch(new ListLoad());

    this.isLoadingResults$.pipe(
      filter((isLoading:boolean) => !isLoading),
      switchMap(() => this.store.pipe(
        select(state => state.stateFragment),
        takeWhile(() => this.componentActive) //unsubscribe
      )),
      map(...)
    ).subscribe(...);

    //Other stuff here

  }

effects.ts

@Effect()
    load$ = this.actions$.pipe(
        ofType(actions.actionTypes.ListLoad),
        withLatestFrom(this.store.pipe(select(state.stateFragment))),
        filter(([action, store]) => {
            let isPageCached: boolean = action.payload in store.stateFragment;
            if (isPageCached) {
                this.store.dispatch(new actions.ListLoaded()); //for sake of changing loading state
            }
            return !isPageCached;
        }),
        switchMap(([action, store]) => {
            return this.service.getAll(action.payload).pipe(
                map(
                    response => {
                        let apiResponse = new ApiResponse(response);
                        return apiResponse.isSuccess ?
                            new actions.ListLoadSuccess({ key: action.payload, data: apiResponse.getData(), totalRecords: apiResponse.getTotalCount() }) :
                            new actions.ListLoadFailed(`code: ${apiResponse.status.error_code}; message: ${apiResponse.status.error_message}`);
                    }
                ),
                catchError(err => observableOf(new actions.ListLoadFailed(err)))
            );
        }
        ), share()
    )

reducer.ts

export function reducer(state = initialState, action: Actions) {
    switch (action.type) {
        case actionTypes.ListLoad:
            return {
                ...state,
                isListLoading: true
            };
        case actionTypes.ListLoaded:
            return {
                ...state,
                isListLoading: false
            };
        case actionTypes.ListLoadSuccess:
            state.listData[action.payload.key] = action.payload.data;

            return {
                ...state,
                isListLoading: false,
                listData: state.listData,
                listTotal: action.payload.totalRecords
            };
        case actionTypes.ListLoadFailed:
            return {
                ...state,
                isListLoading: false,
                error: action.payload
            };
        case actionTypes.ListClear:
            return {
                ...state,
                listData: {},
                listTotal: 0
            };;
        default:
            return state;
    }
}