Angular 路由器事件未结束

Posted

技术标签:

【中文标题】Angular 路由器事件未结束【英文标题】:Angular Router Event does not ended 【发布时间】:2019-02-09 01:36:25 【问题描述】:

当我单击列表中的特定项目时呈现“产品编辑页面”时出现问题。

我有一个从 firebase firestore 检索特定数据的服务方法。

product.service.ts

/**
* Get specific product
*/
getProduct(guid: string): Observable<IProduct> 
return new Observable((observer) => 
      this.firebaseDb.collection('products')
        .doc('XNRkodfbiRoKc2DYPA3o')
        .onSnapshot((querySnapshot) => 

          let product: IProduct;
          product = <IProduct>querySnapshot.data();
          product.guid = guid;

          observer.next(product);

        , (error) => console.log(error.message));
    );

上面的方法会在我的Resolver中被调用,如下图。

product-resolver.service.ts

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<IProduct> 
const id = route.params['id'];

return this.productService.getProduct(id)
              .pipe(
                map(product => 
                  if (product) 
                    return product;
                  
                  console.log(`Product was not found: $id`);
                  this.router.navigate(['/products']);
                  return null;
                ),
                catchError(error => 
                  console.log(`Retrieval error: $error`);
                  return of(null);
                )
              );

product-routing.module.ts

  
    path: 'products/:id/edit',
    component: ProductEditComponent,
    canActivate: [AuthGuardService],
    resolve:  product: ProductResolver 
  

现在的问题是,每当我从列表中单击编辑按钮时,什么都没有发生。这应该被重定向到我的编辑产品页面并使用 this.route.snapshot.data['product'] 填充文本框中的所有数据。

我通过将enableTracing: true 传递给我的路由来调试路由,它似乎卡在Router Event: ResolveStart 中。有人可以启发我为什么这是这种行为吗?

【问题讨论】:

不要为 firebase 查询创建新的 observable,而是使用 fromPromise,这在理解和代码数量方面效率更高。 @trichetriche 你能发布一些与上述代码相关的 fromPromise 的代码快照吗?谢谢! 或者你可以make a quick google search ... 【参考方案1】:

路由器等待 observable 完成。确保在使用take(1)first() 发出第一个值后完成。例如:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<IProduct> 
    return this.productService.getProduct(route.paramMap.get('id')).pipe(
      take(1),
      map(product => 
        if (!product) 
          // noinspection JSIgnoredPromiseFromCall
          this.router.navigate(['/404']);
          return null;
         else 
          return product;
        
      )
    );
  

附:你可以像这样清理你的getProduct 方法:

getProduct(guid: string): Observable<IProduct> 
    return from(this.firebaseDb.collection('products').doc('XNRkodfbiRoKc2DYPA3o').onSnapshot()).pipe(
        map((snapshot:any) => 
            const product = <IProduct>snapshot.data();
            product.guid = guid;
            return product;
        ),
    ); 

【讨论】:

这行得通!那么,在我上面的服务中,我也可以调用“observer.complete()”来完成observable吗?是否需要调用 complete() ?非常感谢! @klaydze 是的,你也可以使用 observable.complete() 。但是,您必须处理 onSnapshot 中的错误情况,例如observable.error(error) 我尝试了您在 getProduct 方法中提供的更新代码,但我很难实现它,因为 onSnapshot 应该有一个基于 firebase 文档的参数 @klaydze 是的,这仅在 guid 是您的实际文档 ID 时才有意义

以上是关于Angular 路由器事件未结束的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2路由器事件监听器

Angular 2路由器:未显示子项

Angular默认子路由未加载父组件

Angular 6 - 路由未发生 - 垫表行

手动传递的 Angular 路由变量在组件中未定义

使用 angular.js 路由手动刷新时仍然出现“未找到”