提问者:小点点

取消路由解决


我正在寻找终止异步路由解析的方法。

这种情况是用户单击一个获取组件所需数据的链接,当它正在解析时,用户回击,或者单击另一个链接。然后我想取消当前的解析并开始新的路由。

我无法通过监听这些更改来拦截路由,因为当现有路由(仍处于解析阶段)正在处理时,没有路由事件订阅触发。

例如,我的路由器可能看起来像:

const appRoutes: Routes = [
{
    path: 'resolvableRoute',
    component: ResolvableRouteComponent,
    resolve: {
      data: RouteResolver
    }
}];

和解析器:

@Injectable()
export class RouteResolver implements Resolve<any> {

    constructor(private http: HttpClient) {}

    public resolve(router: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
        return this.http.get('api/path/for/data');
    }
}

在超文本传输协议调用以任何方式返回之前,路由器或多或少会被卡住。

我有一个很好的加载器,在路由转换时启动,我不想显示新组件,直到我有该组件所需的数据,但我需要能够终止请求。

例如,如果我没有使用解析器,用户可以在组件获取数据时离开组件(例如在init上),因为我可以解构组件并终止超文本传输协议请求。这样做组件的缺点是,当我在处理获取数据时,我要么必须显示空白页面,要么显示不完整的页面。


共2个答案

匿名用户

这对我来说效果很好(角度7)

旋转变压器

public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    return new Observable((observer) => {
      this.http.get().pipe(
        tap(data => {
          if (data !== undefined) {
            observer.next(data);
          }
          else {
            observer.unsubscribe();
          }
          observer.complete();
        })
      ).subscribe();
    });
  }

组件

public ngOnInit() {
    this.route.data.subscribe((parameters: { data: { objs: MyObjs[] } }) => {
      if (parameters.data) {
        this.dataSource = new MatTableDataSource(parameters.data.objs);
        this.dataSource.sort = this.sort;
      }
    });
  }

服务

  public get(): Observable<any> {
    return this.http.get<any>(`${environment.apiUrl}/api/get`).pipe(
      map((response: ApiResponse) => {
        return response.data    
      }),
      catchError(err => of(undefined))
    );
  }

匿名用户

我现在要把我的解决方案作为一个答案,因为这个工作做了我需要的事情,也许它也会帮助别人。

这个解决方案的缺点是我需要路由器的包装,而我宁愿不需要。

理想情况下,我可以创建路由器导航队列的订阅,但所有这些方法/变量在角路由器中都是私有的,因此我无法访问它们。

相反,我创建了一个RouterService,让我在新的导航事件触发时触发一个事件:

@Injectable()
export class RouterService {

    protected navigateListener = new EventEmitter<any>();

    constructor(private router: Router) {}

    public subscribe(generatorOrNext?: any, error?: any, complete?: any) {
        return this.navigateListener.subscribe(generatorOrNext, error, complete);
    }

    public navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
        this.navigateListener.next();
        return this.router.navigate(commands, extras);
    }

    public navigateByUrl(url: string | UrlTree, extras?: NavigationExtras): Promise<boolean> {
        this.navigateListener.next();
        return this.router.navigateByUrl(url, extras);
    }

}

然后在我的Resolve中,我创建了一个可观察的(通常想要返回超文本传输协议请求),但也在侦听RouterService上的事件更改。如果发出路由导航,那么我终止超文本传输协议请求,并让Promise知道它可以完成…

public resolve(router: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
        return new Promise((resolve: any, reject: any) => {
                const subscription = this.http.get('/path/to/some/url').subscribe((data) => {
                    resolve(data)
                }, (error) => {
                    reject({
                        ngNavigationCancelingError: true
                    });
                });

                this.router.subscribe(change => {
                    subscription.unsubscribe();
                    reject({
                        ngNavigationCancelingError: true
                    });
                });
        });
    }