Angular 2:Resolver中Promise拒绝时如何取消路由导航并留当前页?
解决Angular Resolver拒绝时取消路由导航的问题
我来帮你搞定这个困扰!你当前的核心问题是在Resolver的catch块里没有正确返回拒绝的Promise,导致Angular无法识别你要取消导航的意图。咱们一步步来修正:
修正后的Resolver代码
首先,把你的Resolver代码改成这样,关键是要返回带有ngNavigationCancelingError: true标记的拒绝Promise:
@Injectable() export class ModelResolver implements Resolve<MyModel> { constructor(private router: Router) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<MyModel | never> { const params = route.params; const model = new MyModel(); return model.init().then((obj: MyModel) => { return obj; }).catch((err: any) => { // 必须return这个拒绝的Promise,Angular才能捕获到取消导航的信号 return Promise.reject({ message: err, ngNavigationCancelingError: true }); }); } }
为什么你之前的方法没生效?
咱们逐个分析你试过的方案:
- 方案1:你在catch里调用了
Promise.reject但没有return它,Resolver会默认认为异步操作成功完成,所以路由还是会跳转到目标页面,甚至触发默认路由重定向。 - 方案2:用
Observable.throw时,如果Resolver返回的是Observable类型,你需要确保整个resolve方法返回的是Observable,并且错误对象里同样带上ngNavigationCancelingError: true。另外要注意,Angular版本不同,Observable的错误抛出方式可能有差异(比如新版本要用throwError而不是Observable.throw)。 - 方案3:返回
null或Observable.empty()时,Resolver会认为数据加载成功(只是空数据),所以路由导航会正常完成,并不会取消。
如果你用RxJS Observable的替代方案
如果你的model.init()返回的是Observable而不是Promise,可以这样写:
import { catchError, throwError } from 'rxjs'; @Injectable() export class ModelResolver implements Resolve<MyModel> { constructor(private router: Router) { } resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<MyModel> { const params = route.params; const model = new MyModel(); return model.init().pipe( catchError(err => { return throwError(() => ({ message: err, ngNavigationCancelingError: true })); }) ); } }
额外注意事项
- 检查你的路由配置,如果有类似
{ path: '**', redirectTo: '/' }的通配符重定向,可能会在Resolver拒绝时触发意外跳转。你可以在全局错误处理器中判断错误是否带有ngNavigationCancelingError标记,避免这种情况。 - 确保你的Angular版本支持
ngNavigationCancelingError这个标记(Angular 5+就已经支持了)。
内容的提问来源于stack exchange,提问作者Pradeep Reddy
相关产品推荐
相关产品推荐

