我正在寻找终止异步路由解析的方法。
这种情况是用户单击一个获取组件所需数据的链接,当它正在解析时,用户回击,或者单击另一个链接。然后我想取消当前的解析并开始新的路由。
我无法通过监听这些更改来拦截路由,因为当现有路由(仍处于解析阶段)正在处理时,没有路由事件订阅触发。
例如,我的路由器可能看起来像:
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上),因为我可以解构组件并终止超文本传输协议请求。这样做组件的缺点是,当我在处理获取数据时,我要么必须显示空白页面,要么显示不完整的页面。
这对我来说效果很好(角度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
});
});
});
}