第一次加载没有数据

No data of first load

我是 NgRx 的新手,正在尝试使用 Effects 和 http 请求检索和缓存分页的 table 数据。 但是在第一次加载页面时(如果页面尚未缓存)我得到的是空页面,即使我对状态对象执行 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 请求

我能够解决它。问题是我正在通过向其添加新的 属性 来更新作为对象的商店的 属性。 Store 不会发出片段更新的事件,因此不会触发 Select 订阅。我已经引入了另一个用于加载状态的布尔参数,我会监听它的变化,如果加载为假(页面已加载),我 select 需要的片段。 我还为页面缓存添加了额外的代码

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;
    }
}