ngrx顺序数据加载

时间:2018-02-06 19:01:58

标签: angular rxjs ngrx

我有一个警卫,我想确保在页面可视加载之前预先加载数据。我一直关注Todd Motto's strategy,预加载只需要一次发送的数据。

问题是,我的方案需要多个调度,其中一些依赖于其他

我需要调度加载对象A,然后我需要使用对象A上的一些数据来加载对象B

为了这个最小的例子,假设我的状态有loading(布尔值)和things[](加载的实体)。当我执行Get操作时,loading会翻转为true。 <{1}}在看不见的成功动作时被翻转为假。

loading

虽然第一个工作正常但等待加载&#34;但后续调度不会在下一个&#34;等待之前将我的canActivate(route: ActivatedRouteSnapshot): Observable<boolean> { // fetches the first `thing` with the route's id this.store.dispatch(new actions.Get(route.params.id)); return this.store .select(selectState) .filter(state => !!!state.loading) .do(state => { // the first `thing` is loaded // now use it to load another `thing` this.store.dispatch(new actions.Get(state.things[0].something)); }) .take(1) .switchMap(() => this.store.select(selectState)) // in the filter, state.loading is false, even though // we just fired a dispatch to say it's loading. // ...because this is checked before the // dispatch can flip the boolean .filter(state => !!!state.loading) .take(1) .switchMap(() => Observable.of(true)) .catch(() => Observable.of(false)); } 状态变量翻转为true为此加载&#34;检查。

非常感谢任何帮助,或者更好的模式。

3 个答案:

答案 0 :(得分:1)

让我们说我的州看起来像这样

{
  user: User;
  userLoaded: boolean;
  userRoles: Role;
  userRolesLoaded: boolean
}

我的目标是在加载用户和userRoles之前不加载路由。

假设我已经为getUserLoaded创建了选择器,而getUserRolesLoaded只为我们各自的属性返回了我的状态的布尔值。

这是我加载多个

的方法
canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
  return this.store.select(getUserLoaded).pipe(
      map(loaded => {
        // if my user is loaded this will be true
        if (!loaded) {
          this.store.dispatch(new fromStore.LoadUser());
        }
      }),
      filter(loaded) => loaded),
      take(1),
      withLatestFrom(this.store.select(fromStore.getUserRolesLoaded)),
      map(([nullData, loaded]) => {
        if(!loaded) {
          this.store.dispatch(new fromStore.LoadUserRoles()
        }
      }),
      withLatestFrom(this.store.select(fromStore.getUserRolesLoaded)),
      filter(([data, loaded]) => loaded),
      take(1)
    );
}

所以这里我首先得到的是我的userLoaded布尔值的状态切片。如果我的用户没有加载,那么我将调度将加载用户的操作。然后我过滤它,以便它不会返回到真,并取一个取消订阅。接下来,我获得了具有getUserRolesLoaded的状态切片,并检查它们是否已加载,如果不是我发送,添加过滤器等待true并取1。

我正在使用rxjs 5.5中引入的管道方法,但是根据您的需要进行转换不应该太难。对我来说,我觉得关键是要了解我选择哪种状态,以确保我检查的是适当加载的数据。

答案 1 :(得分:0)

也许试试这个快速黑客

.take(1)
    .switchMap(() => this.store.select(selectState).pluck('loading').distingUntilChanged()
)

只有在从false切换为true时才触发,反之亦然。或者使用中间状态,beforeload-&gt; loading-&gt;加载

答案 2 :(得分:0)

我正在努力查看为什么的代码是否如此工作,以防万一其他人在想:

@ ngrx / store State类使用rxjs watchOn运算符和queueScheduler创建了一个Observable actionsOnQueue。这些排队的动作被馈送到减速器以产生新状态。然后,新状态将发出并触发任何选择器。

第一个分派在解析器的上下文中执行并同步运行。下一行创建一个Observable,该Observable从商店中选择,并立即看到Get操作的效果。因此,筛选器将忽略loading = true的初始状态,并且管道会等待加载完成。

稍后分发并减少成功操作(设置loading = false)时,商店将发出并且过滤器将通过。然后将执行第二次调度。 queueScheduler表示此调度将不会同步执行,因为我们正在“成功”执行调度的内部。

然后,在第二个“获取”操作被简化为状态之前,switchMap将再次订阅商店。