处理Resolve服务中的错误

Ste*_*ens 18 rxjs typescript angular

假设我有一个ValuesComponent显示ValueHTML表格中的数组.

// in value.ts
export class Value { ... }
Run Code Online (Sandbox Code Playgroud)
// in values.component.ts
@Component(...)
export class ValuesComponent { ... }
Run Code Online (Sandbox Code Playgroud)

作为一名优秀的程序员,我创造了一个不同的类,负责提供价值.我们称之为ValuesService.

// in values.service.ts
@Injectable()
export class ValuesService
{
    public getValues(): Observable<Value[]>
    {
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

假设服务从Web服务获取其值: /api/values

现在,我想让Angular路由器在导航到组件之前预先获取值,而不是将服务直接注入到我的组件中.

为此,我创建了一个Resolve服务类并将其插入路由器模块.

// in values-resolver.service.ts
export class ValuesResolverService implements Resolve<Value[]> {
    constructor(private backend: ValuesService) {
    }

    public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Value[]> {
        return this.backend.getValues();
    }
}
Run Code Online (Sandbox Code Playgroud)
// In app.module.ts (in @NgModule())
imports: [
  RouterModule.forRoot([{
    path: 'values',
    component: ValuesComponent,
    resolve: { values: ValuesResolverService }
  }])
]
Run Code Online (Sandbox Code Playgroud)
// In values.component.ts
public values: Value[];

constructor(private route: ActivatedRoute) {
}

ngOnInit() {
    this.values = route.data.values as Value[];
}
Run Code Online (Sandbox Code Playgroud)

我到目前为止怎么样?好?然后我在哪里进行ValuesService.getValues()失败时的错误处理?(连接错误,内部服务器错误,......)

当用户尝试导航到/#/values路由并发生错误时,我想将错误记录到控制台并停止导航.理想情况下,我想将用户重定向到/#/error路由(未在示例代码中显示).

Jea*_* A. 3

在这种情况下,服务应该处理错误,并重定向到所需的路由。然后,catch 方法应该返回一个空的 Observable(供解析守卫解析),同时在解析期间处理空情况。

像这样的东西

export class ValuesService {
    constructor(private http:Http, private router:Router) {}

    getValue() {
       this.http.get('/some/url').map((response:Response) => {
           // Map your response to a model here
       }).catch((response:Response) => {
           // Handler case for different status
           this.router.navigate(['/error']);
           return Observable.empty();
       })
    }
}
Run Code Online (Sandbox Code Playgroud)

守卫就像下面这样

export class ValueResolveGuard implements Resolve<Value[]> {

    constructor(private valueService:ValueService) {}

    resolve() { // You don't need the route & state if you're not gonna use them
        this.valueService.getValue().toPromise().then((values:Values[]) => {
            if (!values) { // For the Observable.empty() case
                // return some default stuff
            }
            return values;
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想专门返回一个可观察量(在这种情况下应该没有任何区别,因为解析守卫接受可观察量和承诺),您可以执行类似的操作。

 this.valueService.getValue().first().catch({} => { 
      // return some default value.
 });
Run Code Online (Sandbox Code Playgroud)

请注意,first() 是必需的,因此返回的可观察量将是终止的可观察量,否则解析守卫将无法解析。需要 catch 是因为对空 observable 的 first() 调用会抛出错误。

  • 我不同意让服务处理一般的导航,但特别是将导航作为失败的 getter 的副作用。我希望我的吸气剂没有副作用。 (5认同)