简体   繁体   English

如何在Angular 4中的http状态200响应的.map中引发可观察到的错误

[英]How to throw observable error in .map for a http status 200 response in Angular 4

In my Angular 4 app, I call a server's login api with http post. 在我的Angular 4应用中,我使用http post调用服务器的登录api。 The server always responds with a stauts 200 whether or not the login was successful. 服务器始终以stauts 200响应,无论登录是否成功。 I want to throw an error based on the server response data. 我想根据服务器响应数据抛出错误。

export class AuthenticationService {
...
login(username: string, password: string): Observable<any> {
    let body = `method=login&username=${username}&password=${password}`;

    return this.http.post('http://localhost/rest.php', body)
        .map((response: Response) => {
            let responsedata = response.json();
            if (responsedata && responsedata.success == 1) {
                localStorage.setItem('loggedin',1);
            } else {
                // Not logged in successfully
                Observable.throw(new Error('Not logged in'));
            }

        });
}

And my code calling login() 和我的代码调用login()

trytologin() {
    this.loading = true;
    this.authenticationService.login(this.model.username, this.model.password)
        .subscribe(
            data => {
                // Always returns here regarless of result of login
                this.router.navigate([this.returnUrl]);
            },
            error => {
                // ONLY returns here on a NON-server 200 status
                this.alertService.error(error);
                this.loading = false;
            });
}

I think I could intercept the response and change the headers by using HttpInterceptor , however this seems like overkill. 我想我可以使用HttpInterceptor截取响应并更改标头,但这似乎HttpInterceptor过头了。 Is there another way to get the subscribe error to trigger from a 200 status response? 还有另一种方法可以使subscribe错误从200状态响应中触发吗?


EDIT 编辑

I tried implementing a HttpInterceptor without success. 我尝试实现HttpInterceptor失败。

import {HttpClient, HttpHeaders} from '@angular/common/http';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse,HttpHeaderResponse, HttpErrorResponse} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/map';

@Injectable()
export class LoginInterceptor implements HttpInterceptor {

constructor() {}

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Need to .map so we can go through each event looking for the HttpResponse
    // Can't use .do() as it doesn't update per the docs
    return next.handle(req).map(event => {
        if (event instanceof HttpResponse) {

            let e2 = new HttpErrorResponse({status: 405, statusText: 'Auth error'});
            // return Observable(e2);   // Cannot return as HttpErrorResponse is NOT part of HttpEvent<any>
            Observable.throw(e2);  // <-- Still triggers the success in .subscribe().  Does NOT trigger the .subscribe() error
            event = event.clone({status: 405, statusText: 'Auth error'});  // <-- change the event status.  Can't return HttpErrorResponse as
        }

        return event;
    });

}
}

The .subscribe() success is always called. 总是调用.subscribe()成功。


I was incorrect. 我错了 :-/ EDIT #2 :-/ 编辑#2

After LOTS of digging, I now know why my code was failing. 经过大量的研究,我现在知道为什么我的代码失败了。 But I still don't have a solution!! 但是我仍然没有解决办法!

The HttpInterceptor is the way to go..... but the Observer.throw() will only work only if the HttpClient.post() is on the same domain!! HttpInterceptorHttpInterceptor的方法..... 但是 Observer.throw() 仅在HttpClient.post()在同一域中才有效! The subscribe() error is called if I post() to localhost. 如果将post()发布到本地主机,则会调用subscribe()错误。 If I call a post() to another domain, it fails to call the subscribe() error. 如果我将post()调用到另一个域,它将无法调用subscribe()错误。 I put a console.log() immediately after the Observer.throw() . 我在 Observer.throw()之后紧接着放置了 console.log() Observer.throw() There is log output if I have a different domain. 如果我有其他域,则有日志输出。 There is no log output if the domain is the same. 如果域相同,则 没有日志输出。 I don't know if this is a CORS issue as I have control over the server output and have included a Access-Control-Allow-Origin: * header item. 我不知道这是否是CORS问题,因为我可以控制服务器输出,并且包含 Access-Control-Allow-Origin: *标头项。

Is this possibly a bug in the HttpClient and/or HttpInterceptor ??? 这可能是 HttpClient和/或 HttpInterceptor的错误 HttpInterceptor Or maybe a problem with rxjs?? 还是rxjs有问题?


Edit #3 编辑#3

If I simply return an Observable.throw() in the intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> block my error code gets triggered. 如果我只是在intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>返回Observable.throw() intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>块, intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>触发我的错误代码。 This however will trigger on the http request only. 但是,这只会在http请求上触发。 I need to process and throw an error on the http response . 我需要处理并在http响应上引发错误。 In order to do this I need to use return next.handle(req).map() to look for each HttpResponse event. 为此,我需要使用return next.handle(req).map()查找每个HttpResponse事件。

If I try and execute an Observer.throw() inside the map() it does NOT trigger my error code and is not caught anywhere. 如果我尝试在map()执行Observer.throw() ,则它不会触发我的错误代码,并且不会在任何地方被捕获。 The line after the Observer.throw() is executed. Observer.throw()之后的行被执行。

I can't return Observer.throw() from the map() as it is the incorrect return type. 我无法从map() return Observer.throw() ,因为它是错误的返回类型。

However, calling a plain javascript throw() inside of the map() will trigger my error code. 但是,在map()调用普通的JavaScript throw() map()会触发我的错误代码。

I'm not sure if a plain throw() is best practice or if I should be doing something else. 我不确定是否最好使用throw()还是应该做其他事情。

You will have to import proper libraries and methods of Observable to get this code working like 您将必须导入适当的Observable库和方法,以使此代码像

import { HttpInterceptor, HttpErrorResponse } from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/Observable/of';

You can intercept the response and from that response you can take a decision, 您可以截取响应,然后从该响应中做出决定,

export class YourInterceptor implements HttpInterceptor{
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
              //check your conditions if fall true send this response as given //below
                return Observable.throw(new HttpErrorResponse({status:401, statusText:"Error of auth"}));
        }
}

Find the screenshot of a sample code that I tried today, 找到我今天尝试的示例代码的屏幕截图, 调用服务的组件代码

浏览器console.log输出

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在角度 http 拦截器中抛出可观察到的错误 - how to throw observable error in angular http interceptor Angular http 响应作为错误参数,即使状态为 200 - Angular http response as error argument, even if the status is 200 Angular 8 Interceptors - 如何处理状态 200 中的响应 - Angular 8 Interceptors - How to process response in status 200 状态为200的URL响应:angular2.0 http帖子为空错误 - Response with status: 200 Ok for URL: null error for angular2.0 http post Angular:Observable with subscribe 返回错误 200 OK 因为响应不是 JSON - Angular: Observable with subscribe returns error 200 OK as the response is not JSON 如果JSON响应中不可用,如何以角度检查http 200状态代码 - How to check http 200 status code in angular if its not available in the json response 如何使用Angular2中的Observable Map函数将Http Service返回的Response对象映射到TypeScript对象 - How to Map Response object returned by Http Service to a TypeScript Objects using Observable Map function in Angular2 Angular 6 HTTP 处理成功响应(成功代码:200)作为错误响应 - Angular 6 HTTP deals with successful Response (Sucess Code: 200) as error response Angular 7 中的 HTTP GET 请求返回错误(状态 200) - HTTP GET Request in Angular 7 returning Error (status 200) 使用Angular HttpClient时如何获取错误响应的HTTP状态? - How to get HTTP status on error response, while using Angular HttpClient?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM