在使用URL参数加载页面之前等待ngrx操作

时间:2016-11-29 17:44:57

标签: angular ngrx

我正在使用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

3 个答案:

答案 0 :(得分:6)

我会使用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();
}

答案 1 :(得分:4)

你需要一个解析器。在完成导航操作之前,解析器会等待数据可用。

@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

答案 2 :(得分:0)

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

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