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】:

为了避免您遇到的问题,我认为您只需要在没有 returnObservable 部分的情况下执行throw 'Credentials mismatch or not existing'。在 observable 执行期间引发的任何错误都将作为当前 Observable 上的错误传播。

目前,您只是将 json 响应替换为 Observable,这不是您想要的。

理想情况下,服务器应该返回错误响应而不是带有错误消息的 json,这会触发订阅中的 error 处理程序。

【讨论】:

不,这是我在尝试返回 Observable.throw() 之前的第一次尝试。

以上是关于Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?的主要内容,如果未能解决你的问题,请参考以下文章

在Angular 10中使用模块化路由时如何正确处理404

CORS 起源问题 - Spring Boot 和 Angular 4

如何正确地将 Polyfills 添加到 SystemJS Angular 4 应用程序

如何正确处理 Angular 中 Scroll 上的导航栏颜色变化?

使用角度谷歌地图时如何正确处理标记点击事件?

如何正确处理服务器端错误?