【问题标题】:Waiting for ngrx action before loading page with URL parameter在加载带有 URL 参数的页面之前等待 ngrx 操作
【发布时间】:2016-11-29 17:44:57
【问题描述】:

我正在使用 ngrx 构建一个 ng2 应用程序。当应用程序启动时,会调用 Web 服务来获取初始数据,一旦获取了这些数据,我就会创建一个 INIT_DONE 操作。

我的状态如下所示:

export interface State {
  documents: Document[];
  selectedDocument: Document
}

当我转到页面 /mypage/456 时,其中 456 是一个 url 参数,我需要获取一些获取的数据,所以我得到这样的 URL 参数:

ngOnInit() {
  this.paramSubscription = this.route.params
    .select<string>('id')
    .map((id) => new SelectAction(id))
    .subscribe(this.store);
}

SELECT_ACTION 在获取的数据中找到元素并设置selectedDocument。问题是 SELECT_ACTION 是在 INIT_DONE 之前创建的,此时 documents 为空。

如何在加载我的页面之前等待 INIT_DONE

【问题讨论】:

    标签: angular ngrx


    【解决方案1】:

    我会使用combineLatest 运算符,因为它结合了多个源流的最新值。此外,我会使用过滤器仔细检查文档是否已设置(这里我假设它是一个数组)。

    ngOnInit() {
      this.subscription = Observable.combineLatest(
          this.store.select("documents")
              .filter(documents => documents.length > 0),
          this.paramSubscription = this.route.params
              .select<string>('id')
      )
      .map((combinedData: [Object[], string]) => combinedData[1])
      .subscribe(this.store);
    }
    

    还将订阅分配给一个变量,以便您可以在组件被销毁时取消订阅。否则,您的订阅将在组件被销毁后仍然存在,并且您的操作仍有可能被发出:

    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
    

    【讨论】:

    • filter iteratee 中有一个错字:documents vs document
    • @JakubBarczyk 谢谢!
    【解决方案2】:

    您需要一个解析器。解析器会等待数据可用,然后再完成导航操作。

    @Injectable()
    export class DocumentsResolver implements Resolve {
    
        constructor(
            private store: Store
        ) {}
    
        resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Hero> {
            // take id from snapshot
            const id = route.params['id'];
            // start with the document list
            return this.store.select('documents')
              // wait until there is data available
              .filter(documents => documents && documents.length > 0)
              // then produce the selected document
              .mergeMapTo(this.store.select('selectedDocument'));
        }
    }
    

    关于路由配置:

    export const DocumentsRoutes: RouterConfig = [
        { path: 'documents/:id', component: DocumentsDetailComponent, resolve: { document: DocumentsResolver } }
    ];
    

    更多关于路由器解析here

    【讨论】:

    • 解析器的问题是加载数据时不会显示 UI...我们无法显示一些进度
    【解决方案3】:

    您可以从商店中选择文档并订阅它并从那里发出您的操作:

    ngOnInit() {
      this.store.select("documents").subscribe(documents => {
        this.paramSubscription = this.route.params
          .select<string>('id')
          .map((id) => new SelectAction(id))
          .subscribe(this.store);
      });  
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-23
      • 1970-01-01
      • 2018-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多