[英]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!!
HttpInterceptor
是
HttpInterceptor
的方法.....
但是 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, 找到我今天尝试的示例代码的屏幕截图,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.