Cancel Route Navigation from Resolver in Angular 2

限于喜欢 提交于 2019-12-07 06:20:13

问题


I needed to cancel the route on promise rejection and stay on the current page without redirecting to default/error page, I have tried different ways of rejecting the promise but ended up resolving the route or redirected to the default route.

@Injectable()
export class ModelResolver implements Resolve<MyModel> {
    constructor(private router: Router) {
    }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {
        let params: any = route.params;

        let model: MyModel= new MyModel();


        return model.init().then((obj: MyModel) => {
                    return obj;
                }).catch((err: any) => {
                    Promise.reject({message: err , ngNavigationCancelingError: true});
            });
    }

}

reject({message: err , ngNavigationCancelingError: true}); // redirects to my default route

return Observable.throw({message: err , ngNavigationCancelingError: true}); // redirects to the current route without cancelling

resolve(null); or return Observable.empty() // redirects to the current route without cancelling


回答1:


In order to cancel route from resolver, you can use observable instead of promise and call: observer.complete() without calling: observer.next()

For example:

 resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot){

   return new Observable((observer) => {
     let somePromiseOrObservableToGetDate=?????;

     somePromiseOrObservableToGetDate.then(data => {
       if (data) {
         observer.next(1);
       }
       observer.complete();
     })
       .catch((err: any) => {
         observer.complete();
       });
   });

 } 

and in your example:

let model: MyModel = new MyModel();

return new Observable((observer) => {
  model.init().then((obj: any) => {
    observer.next(obj);
    observer.complete();
  })
    .catch((err: any) => {
      observer.complete();
    });
});



回答2:


Using Angular 6 the only way I could prevent the navigation from happening was throwing an unhandled error from the resolver stream. The simplest way to test this out:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    // throwError imported from 'rxjs'.
    return throwError('some error object');
}

The navigation would also not happen if you'd return a stream that never completes (ie. NEVER from 'rxjs') but then the router would keep on waiting for the stream to either complete or error (which never happens) meaning all routing operations will stop working.




回答3:


Use this work around to reject and stay on the same page for route resolver.

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<any> {

        return new Promise((resolve, reject) => {
            return model.init().then((obj: any) => {
                resolve(obj);
            }).catch((err: any) => {
                this.router.navigateByUrl(this.location.path());
                resolve(false);
            });
        });

    }



回答4:


One way to cancel navigation is to complete an Observable without returning any data. I couldn't find a documentation on this behavior, but seems to be working.

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    let params: any = route.params;
    let model: MyModel= new MyModel();
    return Observable.fromPromise(model.init()).pipe(
        catchError((err: any) => Observable.empty());
}


来源:https://stackoverflow.com/questions/48402208/cancel-route-navigation-from-resolver-in-angular-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!