Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?
Posted
技术标签:
【中文标题】Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?【英文标题】:Angular 4: How to properly handle app level http error as Observable error? 【发布时间】:2018-02-04 13:30:11 【问题描述】:我使用 HTTP API 通过 json 返回应用级错误,其中 status == 'error'。
在我的注册服务中,我这样做:
return this.userService
.create(user)
.map(
json =>
console.log(json);
if (json.status=='error')
console.log('error return throw');
return Observable.throw('Credentials mismatch or not existing');
const user = json.data as User;
return user;
,
err =>
console.log(err);
);
在我的 singUp.component 中,我这样做了:
onSubmit()
// blahblah
this.si
.signUp(this.credentials.emailAddress, this.credentials.password, this.credentials.zipCode)
.subscribe(
user =>
console.log(user);
console.log(`SignUpComponent.onSubmit() found user.userId $user.userId`);
this.router.navigate(['signin']);
,
err =>
this.errorMessage = `*** SignUpComponent: Error while signing up err`;
console.error('*** SignUpComponent: Error while signing up', err);
this.resume();
//this.router.navigate(['signup']);
);
this.ngOnChanges();
不幸的是,当服务返回错误(使用 Observable.throw())时,组件不会触发 err 闭包,而是用户闭包将 Observable.throw 作为用户参数传递。
我希望我能触发 err 关闭。
我错过了什么?
更新:这是我得到的:
[Log] SigninService.signUp, zipCode=
[Log] data: null, status: "error", message: "Error user create: - missing id API usage v1b3: Tu…ate\"↵post: []↵.↵", ws: "v1b3: Tuesday, August 25th 2017 20h20 @ Tanger"
[Log] error return throw
[Log] ErrorObservable _isScalar: false, error: "Credentials mismatch or not existing", scheduler: undefined, _subscribe: function, …
[Log] SignUpComponent.onSubmit() found user.userId undefined
【问题讨论】:
你的.map()
在做什么?
它会查找 API 状态以确保 API 返回全新用户(当 status=='success' 时)。如果状态等于“错误”(代表未创建用户帐户),我希望“为订阅者生成错误”。
这行得通吗?
我在问题中添加了日志
【参考方案1】:
我终于想出了以下解决方案,扩展了以下事实:1)使用 throw new Error() 我仍然可以返回一个 Observable 并且 2)当错误抛出时,订阅完成参数不会触发,需要使用finally() 调用如下:
注册服务:
create(user: User): Observable<User>
const wsUrl = `$this.wsApim=create&id=$user.id`; // URL to web api
return this.http.post(wsUrl, JSON.stringify(user), headers: this.headers )
.retry(3)
.map(res =>
const json = res.json() as any;
if (json.status=='error') throw new Error(json.message);
return json.data as User;
);
注册组件:
onSubmit()
// blahblah
this.progressing = true;
this.si
.signUp(this.credentials.emailAddress, this.credentials.password, this.credentials.zipCode)
.finally(() => setTimeout(() => this.progressing = false, 1000))
.subscribe(
user => this.router.navigate(['signin']),
err => this.errorMessage = err
);
this.ngOnChanges();
【讨论】:
【参考方案2】:您正在处理用户回调中的异常,这意味着它已成功执行,在这种情况下Observable.throws
不会真正充当异常。为了实现这一点,您必须使用必须替换 return Observable.throw("Credentials mismatch or not existing")
的 throw new Error("Credentials mismatch or not existing")
;请看这个:How to throw error from RxJS map operator (angular)
【讨论】:
感谢@dag 让我走上正轨。将您的答案修改为: throw new Error("Credentials mismatch or not existing");必须替换 return Observable.thow("Credentials mismatch or not existing");这样我才能接受。【参考方案3】:为了避免您遇到的问题,我认为您只需要在没有 return 和 Observable 部分的情况下执行throw 'Credentials mismatch or not existing'
。在 observable 执行期间引发的任何错误都将作为当前 Observable
上的错误传播。
目前,您只是将 json 响应替换为 Observable
,这不是您想要的。
理想情况下,服务器应该返回错误响应而不是带有错误消息的 json,这会触发订阅中的 error
处理程序。
【讨论】:
不,这是我在尝试返回 Observable.throw() 之前的第一次尝试。以上是关于Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?的主要内容,如果未能解决你的问题,请参考以下文章
CORS 起源问题 - Spring Boot 和 Angular 4
如何正确地将 Polyfills 添加到 SystemJS Angular 4 应用程序