首页 > 解决方案 > 在路由解析器中使用订阅

问题描述

我想向服务询问一些数据,以允许路由解析器采取特定操作。

服务应该返回的数据,并不是路由解析后组件要使用的数据,这是解析器的明确用途,也解释了为什么解析器必须返回一个 Observable。

我真正需要服务返回的数据,是在完全解决路由之前在几个可能的操作之间做出决定。

为什么我会陷入这种境地?

我的情况是,带有 slug 参数的顶部 url 可能需要呈现不同的组件。

示例

example.com/whatever-post-slug --> 需要加载 PostComponent
example.com/other-page-slug --> 需要加载 PageComponent
example.com/new-slug-for-random-post --> 需要加载 PostComponent
...

为什么我不只是为路线添加前缀?

因为我不可以。我正在为 WordPress 创建一个主题,并允许帖子和页面使用类似的 url。有关更多详细信息,请参阅此问题

我的解析器实际上在做什么?

我将只显示部分代码,以使其易于掌握:

resolve(route: ActivatedRouteSnapshot): Observable<any>|any{
   this.wprestNoAuthSrv.getPermalinkStructure()
       .pipe(takeUntil(this.unsubscribeOnDestroy))
       .subscribe(
       // ... check httpResponse and decide where to go
          this.router.navigate(route, { skipLocationChange: true });
       )
}

由于我在解析器中订阅,与正在解析的路由关联的组件在导航()发生之前加载。

这会导致非常难看的导航效果。

问题是

我怎样才能阻止这种情况发生,同时仍然使用该订阅?

我实际上希望该组件永远不会加载,因为总会有navigate()事情发生。

如果您意识到,我将{ skipLocationChange: true }其放入router.navigate(),因为我希望用户将路径保留在浏览器中。

我知道这看起来好像我在滥用 Angular 的路由系统,但我想达到这个结果。

这个问题与我想动态加载不同组件的事实无关(为此我发布了上面链接的问题)

这个问题是关于选择的方法,它是有效的,但有一个我想避免的缺点。

一个有效的想法

这个想法有效,但也许您知道更好的解决方案。如果我创建一个 observabe 并在resolve()方法中返回它,我可以强制解析器等待,并且重定向将在它完成时完成。

return Observable.create(observer => {
  setTimeout(() => {
    observer.next("Finished");
    observer.complete();
  }, 5000);
});

当然,这是一个很大的谎言,而且不是很好。即使它工作得很好,我也需要知道这是否是一件非常糟糕的事情,或者是否有更好的选择。

标签: angularrxjsangular2-routing

解决方案


看起来您正试图在解析器内部进行重定向,而在 Observable 内部订阅绝不是一个好主意。这应该符合您的期望:

resolve(route: ActivatedRouteSnapshot): Observable<any>|any{
   return this.wprestNoAuthSrv.getPermalinkStructure().pipe(
     takeUntil(this.unsubscribeOnDestroy),
     mergeMap(httpResponse => {
       // ... check httpResponse and decide where to go
       this.router.navigate(route, { skipLocationChange: true });
       return EMPTY;
     })
   );
}

推荐阅读