我正在try 使用解析器来制作更好的用户体验.在快乐的道路上,一切都很顺利.我似乎不知道如何处理异常.我的解析器调用一个服务,该服务会命中一个webapi项目.举个例子:

FooResolver:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Foo> {
      return this.fooService.getById(route.params['id']).catch(err => {
    ****not sure what to do/return in the case of a server error****
    return Observable.throw(err);
  });
} 

FooService:

  public getById(id: string): Observable<Foo> {
    return this.http.get(`${ this.apiUrl }/${ id }`)
        .map(this.extractData)
        .catch(this.handleError);
}

The handleError function:

   protected handleError (error: Response | any) {
    // Todo: Log the error   
    // Errors will be handled uniquely by the component that triggered them
    return Observable.throw(error);
}

在FooComponent内部,我这样做(在服务/解析器返回错误的情况下,这不会被命中):

FooComponent:

ngOnInit(): void {
    this.foo= this.route.snapshot.data['foo'];
    if (this.foo) {
       this.createForm(this.foo);
    }
}

我已经try 抛出错误(如图所示)-我在控制台中得到这个异常:

未捕获(promise 中):响应状态:500内部服务器错误

然后返回new Observable<Foo>(),这将给出:

无法读取未定义的属性"subscribe"

我有几个解析器,它们都可能在服务器上遇到异常,但我不知道在出现这些异常时该怎么办.

推荐答案

下面是我的一个具有错误处理功能的解析器的示例,使用Gunter建议的技术:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/of';

import { IProduct } from './product';
import { ProductService } from './product.service';

@Injectable()
export class ProductResolver implements Resolve<IProduct> {

    constructor(private productService: ProductService,
                private router: Router) { }

    resolve(route: ActivatedRouteSnapshot,
            state: RouterStateSnapshot): Observable<IProduct> {
        let id = route.params['id'];
        if (isNaN(+id)) {
            console.log(`Product id was not a number: ${id}`);
            this.router.navigate(['/products']);
            return Observable.of(null);
        }
        return this.productService.getProduct(+id)
            .map(product => {
                if (product) {
                    return product;
                }
                console.log(`Product was not found: ${id}`);
                this.router.navigate(['/products']);
                return null;
            })
            .catch(error => {
                console.log(`Retrieval error: ${error}`);
                this.router.navigate(['/products']);
                return Observable.of(null);
            });
    }
}

你可以在这里找到完整的例子:https://github.com/DeborahK/Angular-Routing在APM最终文件夹中.

UPDATE Feb 2019

以下是在解析器中处理错误的更好答案:

  1. 使用可选错误属性将界面包装到另一个界面中:
/* Defines the product entity */
export interface Product {
  id: number;
  productName: string;
  productCode: string;
  category: string;
  tags?: string[];
  releaseDate: string;
  price: number;
  description: string;
  starRating: number;
  imageUrl: string;
}

export interface ProductResolved {
  product: Product;
  error?: any;
}
  1. 解析到该接口:
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

import { ProductResolved } from './product';
import { ProductService } from './product.service';

@Injectable({
  providedIn: 'root',
})
export class ProductResolver implements Resolve<ProductResolved> {
  constructor(private productService: ProductService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ProductResolved> {
    const id = route.paramMap.get('id');
    if (isNaN(+id)) {
      const message = `Product id was not a number: ${id}`;
      console.error(message);
      return of({ product: null, error: message });
    }

    return this.productService.getProduct(+id).pipe(
      map((product) => ({ product: product })),
      catchError((error) => {
        const message = `Retrieval error: ${error}`;
        console.error(message);
        return of({ product: null, error: message });
      }),
    );
  }
}
  1. 在组件中,拉出所需的界面:
ngOnInit(): void {
  const resolvedData: ProductResolved = this.route.snapshot.data['resolvedData'];
  this.errorMessage = resolvedData.error;
  this.product = resolvedData.product;
}

Angular相关问答推荐

如何在Angular功能路由保护中取消订阅RxJs主题

对REST后端的Angular/Priming过滤器请求导致无限循环

Angular 15 Ref 错误:初始化前无法访问组件 A

VSCode 调试器空白页面并在使用 VS Code 1.76.1 和 Chrome 111 启动时加载

通过 SignalR 事件组件重定向Angular 页面后不起作用

Angular 项目构建仅在 GitHub Actions 上失败

带有数据的 Angular 模板

Angular 服务decorator 提供在延迟加载的根效果

类继承支持

如何重新加载当前页面?

react表单上的自定义验证器用于密码并确认密码匹配将未定义的参数导入 Angular 4

*ngIf 和 *ngFor 在 元素上使用

缺少 .angular-cli.json 文件:Angular

运行 npm 测试(Angular 2 单元测试)后无法读取未定义的属性 subscribe

Angular 5 中服务的生命周期是什么

请求 http.GET 时发送的 Angular2 OPTIONS 方法

如何在 Angular 应用程序中通过路由更改页面标题?

ng-template 上的 *ngFor 不输出任何内容

如何对 *ngFor 应用数量限制?

如何将从后端渲染的参数传递给angular2 bootstrap 方法