Angular 4组件如何从Service的HTTP Post请求获取返回对象
Angular 4: 无法获取HTTP Post请求返回数据的问题解决
你遇到的问题核心是HTTP请求的异步特性——console.log在请求完成前就执行了,这时候loginRes还没被赋值,自然拿不到正确的数据。
问题原因详解
Angular的Http.post返回的是一个Observable,它是异步执行的:
- 你调用
subscribe时,只是注册了请求完成后要执行的回调函数,此时HTTP请求还在后台发送,代码会继续往下执行console.log。 - 当请求成功返回后,
subscribe的next回调才会触发,给loginRes赋值,但这时候console.log早就跑完了。
解决方案
把所有需要使用响应数据的逻辑(包括console.log)放到subscribe的回调函数内部,确保数据返回后再执行。另外我们可以优化Service的代码,提前处理响应转换,让组件更简洁。
优化后的LoginService.ts
import { Injectable } from '@angular/core'; import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; import { LoginRequest, LoginResponse } from './your-model-path'; // 替换成你的模型路径 import { Constant } from './your-constant-path'; // 替换成你的常量路径 @Injectable() export class LoginService { constructor(private http: Http) { } login(loginReq: LoginRequest): Observable<LoginResponse> { return this.http.post(Constant.API_URL + "weblogin", loginReq) // 提前把响应转成LoginResponse类型 .map((res: Response) => res.json() as LoginResponse) // 统一处理错误,返回一个包含错误信息的LoginResponse .catch((error: any) => { const errorRes = new LoginResponse(); errorRes.message = "Failed to connect the server"; errorRes.status = "NOT_OK"; return Observable.of(errorRes); }); } }
优化后的LoginComponent.ts
import { Component } from '@angular/core'; import { LoginService } from './login.service'; import { LoginRequest, LoginResponse } from './your-model-path'; @Component({ // 你的组件元数据 }) export class LoginComponent { loginRes: LoginResponse; loginReq: LoginRequest = new LoginRequest(); // 初始化请求对象 constructor(private loginService: LoginService) { } login() { this.loginService.login(this.loginReq).subscribe( (res: LoginResponse) => { this.loginRes = res; // 在这里处理响应数据,包括console.log console.log(this.loginRes.message + " Response Data"); // 其他需要用loginRes的逻辑也放在这里 } // 因为Service已经处理了错误,这里可以不用额外处理错误回调,除非需要组件级别的特殊逻辑 ); } }
额外说明:为什么这样改?
- Service职责单一:Service负责发送请求、转换响应、处理通用错误,组件只需要关注业务逻辑。
- 异步逻辑正确执行:所有依赖响应数据的代码都在
subscribe回调内,确保数据准备好后再执行。 - 类型安全:通过
map操作符提前转换类型,组件拿到的直接是LoginResponse对象,不用再手动转换。
如果你想用async/await的方式(更像同步代码的写法),也可以把Observable转换成Promise:
async login() { try { this.loginRes = await this.loginService.login(this.loginReq).toPromise(); console.log(this.loginRes.message + " Response Data"); } catch (error) { // 处理错误 } }
不过这种方式需要导入rxjs/add/operator/toPromise。
内容的提问来源于stack exchange,提问作者Zaw Than oo
相关产品推荐
相关产品推荐

