Angular 如何让HTTP Service返回可迭代、可调用get方法的ES6 Map
问题根源
Angular HttpClient的泛型仅为TypeScript编译期的类型提示,不会在运行时做实际的类型转换:后端返回的JSON数据会被默认解析为普通JavaScript对象,并不是你声明的Map类型,自然没有迭代器、get等Map原型上的方法。
解决方案
调整Service中的请求处理逻辑,在响应流中新增转换步骤,把普通对象手动转为ES6 Map实例:
步骤1:导入rxjs map操作符
在Service文件头部导入依赖:
import { map } from 'rxjs/operators';
步骤2:修改getLayout方法的响应处理
在pipe中新增map操作符完成类型转换,修改后的完整方法如下:
getLayout(dims: Map<number, [number, number]>, rels: [number, number][]): Observable<Map<number, [number, number]>> { // ES6 Map 无法直接序列化,转成普通对象再提交 let jsonDims: { [x: number]: [number, number]; } = {} dims.forEach((dim, gid) => { jsonDims[gid] = dim }); const data = { "dims": jsonDims, "rels": rels } return this.http.post<Record<number, [number, number]>>( // 先声明实际返回的是普通键值对对象 environment.backend_url + '/layout', JSON.stringify(data), this.options ).pipe( map(res => { // 手动将普通对象转为ES6 Map实例 return new Map( Object.entries(res).map(([keyStr, pos]) => [Number(keyStr), pos as [number, number]]) ) }), catchError(err => { console.error(err.message) return throwError("Error occurred while requesting layout.") }) ); }
步骤3:组件代码无需修改
此时subscribe拿到的layout就是真正的ES6 Map实例,支持for...of迭代、get()、set()等原生Map方法,原有组件逻辑可以直接运行。
注意事项
- 如果后端返回的是
[[key1, value1], [key2, value2]]格式的键值对数组,可以省略Object.entries步骤,直接new Map(res)即可 - 转换时注意键的类型匹配:如果你的Map键是数字类型,需要把JSON解析后得到的字符串键手动转为数字,避免后续类型不匹配的问题
内容的提问来源于stack exchange,提问作者TehQuila
相关产品推荐
相关产品推荐

