在Angular2中,如何拦截来自observable的错误响应并将其传递给错误通道

cam*_*cam 11 rxjs angular

我有一个与api服务器交互的服务.它有myHttpPost(数据)方法.这种方法应该:

  1. 将Angular的http.post调用到服务器
  2. 如果响应具有状态200,则向订户提供响应的json内容
  3. 如果响应具有不同的状态,则处理响应并向订户提供已处理的错误

我方法的当前版本是:

postData(path: string, data: Object): Rx.Observable<any> {
    let json = JSON.stringify(data);
    return this.http.post(path, json)
        .map(res => res.json())
}
Run Code Online (Sandbox Code Playgroud)

这不是从上面的列表中进行的第3点,因为map仅在成功时调用,而不是在出错时调用.我可以通过添加以下内容来更改序列

.catch(error => {
    let myError = prepareErrorContent(error);
    return Rx.Observable.throw(myError);
});
Run Code Online (Sandbox Code Playgroud)

然后订阅者(另一个服务)收到myError(没关系),但是rxjs文档说明了以下关于catch()方法的内容:"继续使用下一个可观察序列的异常终止的可观察序列." 但我希望序列正常终止而不是继续.如果我使用catch()上面的类似,那么从订阅者下一次调用postData()不起作用(它会立即返回相同的错误,而不是进行http调用).我认为这是因为序列没有终止.

怎么做?

[编辑]这是我使用此服务的订阅者方法:

 this.jsonHttp.postData(path, data)
    .subscribe(
        struct => onNext(struct),
        error => {
            let message = this.jsonHttp.extractError(error);
            onError(message)
        },
        () => onComplete ? onComplete() : null
    );
Run Code Online (Sandbox Code Playgroud)

Thi*_*ier 18

实际上,对于每个HTTP请求,都会创建并执行处理链.收到响应(成功和出错)后,链完成.

如果执行两次请求,则它们之间没有链接.当两个请求都属于同一个处理链时,您可以拥有一些链接.例如,当使用像flatMap或等可观察的运算符时switchMap.这是一个示例:

return this.http.get(...)
        .map(res => res.json())
        .flatMap(jsonData => {
          // Can leverage the result of the previous request 
          return this.http.get(...).map(res => res.json());
        });
Run Code Online (Sandbox Code Playgroud)

发生错误时,处理链断开并catch调用操作符.您可以在关联的回调中返回一个observable来继续处理链.它可以是经典的可观察的,也可以是错误的Observable.throw.在Angular2中的HTTP请求的上下文中,状态代码不同于2xx的响应被视为错误.

返回时Observable.throw,调用订阅时指定的第二个回调.如果它是另一个可观察的,则调用第一个回调.例如:

return this.http.get(...)
        .map(res => res.json())
        .catch(res => {
          // The error callback (second parameter) is called
          return Observable.throw(res.json());
          // The success callback (first parameter) is called
          // return Observable.of(res.json());
        });
Run Code Online (Sandbox Code Playgroud)

我实现了一个执行请求(单击按钮)而没有身份验证标头的plunkr,因此收到401状态代码.再次单击时,会添加标头,因此会收到200状态代码.只是为了告诉你这两个请求之间没有关系.

请参阅此plunkr:https://plnkr.co/edit/5WwWpwjvQmJ4AlncKVio ? p = preview .