Angular 6 HTTPClient问题:请求仅触发一次却收到两次响应
Angular 2升级到6后登录POST请求问题排查方案
嘿,我来帮你捋捋Angular 6里登录POST请求的问题!毕竟从Angular 2升级到6,HttpClient和拦截器的细节变化不小,咱们一步步排查:
1. 先确认AuthService是否切换到了HttpClient
Angular 4.3之后就推荐用HttpClient取代旧的Http了,如果你还在沿用Angular 2的Http写法,肯定会出问题。
错误的旧写法(Angular 2):
import { Http } from '@angular/http'; @Injectable() export class AuthService { constructor(private http: Http) {} signIn(account: any) { return this.http.post('/api/login', account) .map(res => res.json()); // 旧Http需要手动解析JSON } }
正确的新写法(Angular 6):
import { HttpClient } from '@angular/common/http'; @Injectable() export class AuthService { constructor(private http: HttpClient) {} // 换成HttpClient signIn(account: any) { // HttpClient默认会自动解析JSON响应,不需要手动map return this.http.post('/api/login', account); // 如果后端返回的是文本而非JSON,要加响应类型配置: // return this.http.post('/api/login', account, { responseType: 'text' }); } }
2. 检查拦截器的实现是否符合Angular 6规范
Angular 6的拦截器需要克隆请求才能修改头部(原请求对象是只读的),而且要确保在模块里正确注册。
正确的拦截器写法:
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // 必须克隆请求再修改头部,不能直接修改原req const modifiedRequest = req.clone({ headers: req.headers.set('Content-Type', 'application/json') // 如果需要加其他头部(比如token),可以继续链式调用set // .set('Authorization', `Bearer ${token}`) }); return next.handle(modifiedRequest); } }
在AppModule里注册拦截器:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { AuthInterceptor } from './auth.interceptor'; @NgModule({ // ...其他配置 providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true // 这个必须加,不然会覆盖默认拦截器 } ] }) export class AppModule {}
3. 确认请求体格式是否匹配后端要求
有时候后端期望的是application/x-www-form-urlencoded而非application/json,这时候需要转换请求体格式:
转换为表单编码格式的示例:
import { HttpParams } from '@angular/common/http'; signIn(account: any) { // 用HttpParams构建表单数据 const formData = new HttpParams() .set('username', account.username) .set('password', account.password); return this.http.post('/api/login', formData.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); }
4. 优化错误日志,定位具体问题
把错误处理的日志打详细点,能帮你快速定位是后端返回错误、请求格式不对还是其他问题:
this.authService.signIn(this.account) .subscribe( res => { console.log('RES -> ', res); this.router.navigate([this.returnUrl]); }, err => { console.log('错误状态码:', err.status); console.log('错误响应体:', err.error); // 这里能看到后端返回的具体错误信息 console.log('完整错误对象:', err); } );
最后小提醒
如果以上都排查过还是有问题,可以看看浏览器控制台的Network面板,检查请求的头部、请求体、响应状态,对比Angular 2时代的请求差异,大概率能找到问题所在。
内容的提问来源于stack exchange,提问作者Damian
相关产品推荐
相关产品推荐

