Angular 4:如何将应用级http错误正确处理为Observable错误?

Angular 4: How to properly handle app level http error as Observable error?

我使用 HTTP API returns 应用级错误通过 json where 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();
    }

不幸的是,当服务 returns 出错时(使用 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

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

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

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

你在用户回调中处理异常,这意味着它已成功执行,在这种情况下 Observable.throws 不会真正充当异常。为了实现这一点,您必须使用必须替换 return Observable.throw("Credentials mismatch or not existing")throw new Error("Credentials mismatch or not existing");请看这个:

我最终想出了以下解决方案,扩展了以下事实:1) 使用 throw new Error() 我仍然可以 return 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();
    }