【问题标题】:Angular 4: How to properly handle app level http error as Observable error?Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?
【发布时间】: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' 时)。如果状态等于“错误”(代表未创建用户帐户),我希望“为订阅者生成错误”。
  • 这行得通吗?
  • 我在问题中添加了日志

标签: angular observable throw


【解决方案1】:

我终于想出了以下解决方案,扩展了以下事实:1)使用 throw new Error() 我仍然可以返回一个 Observable 并且 2)当错误抛出时,订阅完成参数不会触发,需要使用finally() 调用如下:

注册服务:

create(user: User): Observable<User> {
    const wsUrl = `${this.wsApi}m=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() 之前的第一次尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    相关资源
    最近更新 更多