【问题标题】:Promise Error in Observable not calling catchObservable 中的 Promise 错误未调用 catch
【发布时间】:2017-12-05 09:24:36
【问题描述】:

我使用 @angular/http 进行 http 调用(Observable)和 NativeStorage 库作为 Promise 的存储机制。这就是我使用 FromPromise 将 Promise 函数 "NativeStorage.getItem("xxx")" 转换为 Observable 的原因。

我什至不确定这是否是一个好习惯,并且链条在“console.log("HIT SUCCESSFULLY");" 行中断了并停止执行代码。

由于存储中没有名为“externalAccessToken”的项目,所以在Promise中捕获异常null是正常的,但我不明白为什么它会停止执行。

到目前为止,我尝试返回 null 以外的其他内容并使用“Promise.reject()”导致“未处理的 Promise 拒绝”错误。

如何让代码保持执行并点击 Observable 的 catch 函数

public getExternalAccessTokenFromStorage(): Observable<any> {
    let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
    let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise.then(x => x)
   .catch(() => {
        console.log("HIT SUCCESSFULLY");
        return null
   }));

    return getExternalAccessTokenFromStorage.map(x => {
        console.log("NOT HIT AT ALL");
        return x;
    }).catch(() => {
        console.log("NOT HIT AT ALL");
        return null;
    });
}



public getUserInfo(): Observable<StoredUserModel> {        
    //Get External Access Token From LocalStorage        

    return this.getExternalAccessTokenFromStorage().flatMap((x: IExternalAccessTokenBindingModel) => {
        return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
            console.log("NOT HIT AT ALL");
            let headers = new Headers();
            headers.append("Authorization", "Bearer " + accessToken.access_token);
            headers.append("Content-Type", "application/json");
            let options = new RequestOptions({ headers: headers });
            var externalBindingModel = JSON.stringify(x);
            return this.http.post(this.baseUrl + '/api/Account/ExternalUserInfo', externalBindingModel, options).map((res: Response) => {
                //ADD USER INTO NATIVESTORAGE
                this.addUserIntoStorage(res.json());
                return res.json();
            });
        });
    }).catch(x => {
        return this.getAccessTokenFromStorage().flatMap((accessToken: AccessTokenModel) => {
            console.log("NOT HIT AT ALL");
            let headers = new Headers();
            headers.append("Authorization", "Bearer " + accessToken.access_token);
            let options = new RequestOptions({ headers: headers });
            return this.http.get(this.baseUrl + '/api/Account/UserInfo', options).map((res: Response) => {
                //ADD USER INTO NATIVESTORAGE
                let user: StoredUserModel = res.json();
                this.addUserIntoStorage(res.json());
                return user;
            });
        }).catch(error => {
            return null;
        });
    });
}

更新问题:

我已移除 Promise.catch 并保留 Observable.catch 以便在 Observable 中捕获未处理的异常;

public getExternalAccessTokenFromStorage(): Observable<any> {
    let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
    let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise);

    return getExternalAccessTokenFromStorage.map(x => {
        return x;
    }).catch(() => {
        return null;
    });
}

我收到以下错误;

【问题讨论】:

  • 为什么不使用Observable.catch 而不是Promise.catch,即将错误处理移出fromPromise
  • 我已经尝试过了,它会抛出类似“未处理的错误”:item null 异常。如果你愿意,我可以产生并写出确切的错误
  • 是的,请提供minimal reproducible example,不要提供任何无关的细节。
  • @jonrsharpe 我已经更新了问题
  • 请注意,您需要从 catch 回调中返回一个 observable - learnrxjs.io/operators/error_handling/catch.html

标签: javascript angular angular-promise angular2-observables


【解决方案1】:

Catch 与编程中的try / catch 子句完全相同。

举个例子:

try {
   throw new Error('bang');
} catch(ex) {
   // do nothing
}

console.log('I'm still reachable');

我们可以像这样用 observable 重现上面的内容:

let o = Observable.create((observer)=>{
     observer.error(new Error('bang'));
}).catch(()=>{ 
    // do nothing
});

o.subscribe(()=>{
   console.log('I'm still reachable');
});

如果您想捕获并处理错误,然后使用try / catch 阻止下面的代码执行,您可以这样做:

try {
   throw new Error('bang');
} catch(ex) {
   // do some logic here
   throw ex;
}

console.log('I cannot be reached');

在 observables 中也是如此。你必须重新抛出错误或产生一个同样失败的 observable。

let o = Observable.create((observer)=>{
     observer.error(new Error('bang'));
}).catch((ex)=>{ 
    // do some logic here
    return Observable.throw(ex);
});

o.subscribe(()=>{
   console.log('I cannot be reached');
});

【讨论】:

  • 感谢您提供详细信息;返回 Observable.throw(ex) 工作
【解决方案2】:

问题是您正在捕捉错误,但没有处理错误。您将希望将错误作为 Observable 抛出。

public getExternalAccessTokenFromStorage(): Observable<any> {
    let externalAccessTokenPromise = NativeStorage.getItem('externalAccessToken');
    let getExternalAccessTokenFromStorage: Observable<any> = Observable.fromPromise(externalAccessTokenPromise);

    return getExternalAccessTokenFromStorage.map(x => {
        return x;
    }).catch((error: any) => 
        Observable.throw(error.json().error || 'Server error');
    );
}

然后您可以以承诺的形式处理您的响应和错误:

this.getExternalAccessTokenFromStorage().subscribe(
  res => console.log(res),
  error => console.log(error));

【讨论】:

  • 你需要返回Observable.throw 否则什么都不会发生。
猜你喜欢
  • 2020-03-10
  • 1970-01-01
  • 2019-07-10
  • 2017-06-29
  • 1970-01-01
  • 1970-01-01
  • 2014-09-18
  • 2021-07-06
相关资源
最近更新 更多