Angular5服务HTTP GET返回Object而非指定泛型Product,调用方法报错如何解决?
问题解答
首先直接给你明确答案:你猜的没错!Angular HttpClient中get<Product>里的泛型仅仅是编译时的类型提示和检查,完全不影响运行时的结果。
为什么会出现这个问题?
当HttpClient收到后端返回的JSON数据后,它会用JSON.parse()把字符串转换成普通的JavaScript对象——这个对象只是拥有和Product类同名的属性,但它并不是Product类的实例,自然没有setQuantity这类原型链上的方法,所以调用时会报错。
接下来给你两种常用的解决方法,帮你拿到真正的Product类实例:
方案一:手动创建Product实例并赋值
最简单的方式是在数据流中把返回的普通对象合并到新的Product实例上:
方式A:用Object.assign快速赋值
修改你的服务代码即可:
public getProductByID(productId: string): Observable<Product> { const headers = new HttpHeaders({ "Content-Type": "application/json" }); const url = `${environment.productservice_baseurl}/${productId}`; return this.http .get<Product>(url, { headers: headers }) .pipe( tap(data => { // 创建新的Product实例,把返回的数据合并进去 this._product = Object.assign(new Product(), data); }), catchError(this.handleError) ); }
方式B:给Product类添加构造函数(更优雅)
先给Product类加一个接收数据的构造函数,方便后续复用:
class Product{ productID:string; productName:string; // 用Partial<Product>允许传入部分属性 constructor(productData: Partial<Product>) { // 把传入的数据合并到当前实例 Object.assign(this, productData); } setQuantity(quantity:number){ // 你的业务逻辑 } }
然后在服务里直接用构造函数创建实例:
tap(data => { this._product = new Product(data); })
方案二:用map操作符统一转换实例
如果你希望整个Observable流输出的都是Product实例(而不仅仅是赋值给this._product),可以用map操作符提前转换:
public getProductByID(productId: string): Observable<Product> { const headers = new HttpHeaders({ "Content-Type": "application/json" }); const url = `${environment.productservice_baseurl}/${productId}`; return this.http .get<Product>(url, { headers: headers }) .pipe( // 先把普通对象转成Product实例 map(data => new Product(data)), tap(data => (this._product = data)), catchError(this.handleError) ); }
这样当你订阅这个方法返回的Observable时,拿到的也会是真正的Product实例,调用setQuantity就没问题了。
内容的提问来源于stack exchange,提问作者Pradeepl
相关产品推荐
相关产品推荐

