Как обрабатывать ошибку в Resolver

Я пытаюсь использовать резольверы, чтобы сделать лучший UX. Все отлично работает на счастливой тропе. Я не могу понять, как справляться с исключениями. Мой resolver вызывает службу, которая попадает в проект 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);
}

Функция handleError:

   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 я делаю это (это никогда не попадает в случае ошибки, возвращенной из службы /resolver):

FooComponent:

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

Я попытался выбросить ошибку (как показано) - я получаю это исключение в консоли:

Неподготовлено (в обещании): Ответ со статусом: 500 Внутренняя ошибка сервера для URL:

и возвращает new Observable<Foo>(), который дает:

Невозможно прочитать свойство "подписаться" неопределенного

У меня есть несколько резольверов, все из которых могут испытывать исключения на сервере, но я не знаю, что делать в случае этих исключений.

Ответ 1

Вот пример одного из моих решателей с обработкой ошибок, используя технику, которую предлагает Гюнтер:

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-final.

Ответ 2

Вам нужно вернуть наблюдаемое, которое заканчивается false

handleError() {
  return Observable.of([false]);
}