Angular 管道之异步数据读取转换
这篇文章由 DeathGhost 编辑,发布于
归类于 Angular » 👋分享到微博 当前评论 1 条。
async 管道会订阅一个 Observable 或 Promise,并返回它发出的最近一个值。 当新值到来时,async 管道就会把该组件标记为需要进行变更检测。当组件被销毁时,async 管道就会自动取消订阅,以消除潜在的内存泄露问题。
每个应用开始的时候差不多都是一些简单任务:获取数据、转换它们,然后把它们显示给用户。
一旦取到数据,你就可以把它们原始值的 toString 结果直接推入视图中。 但这种做法很少能具备良好的用户体验。
例如,在项目应用中前端通过请求后端程序接口,往往会返回一些数字、字符或原始数据形式标识,常见的日期这类信息,通常会直接显示原始数据,用户可读性很差Sun Sep 22 2019 00:00:40 GMT 0800 (中国标准时间)
等等诸如此类的数据信息,用户阅读起来比较困难,因此我们需要将其转换为2019-09-22
这般方可。
这种情形下,在Angular中我们就需要使用管道对其转换,进而达到用户可读数据。更多管道信息,这里不多解释说明,下面看看关于Angular中异步数据信息管道的使用。
示例需求:通过请求获取本地城市JSON文件对城市编码创建管道
(前提场景:本地数据,数据库仅存储城市编码)
首先创建一个本地json文档,数据结构如下:
[
{value: '001', label: '北京', isLeaf: true},
{value: '002', label: '上海', isLeaf: true},
{value: '003', label: '陕西省', children: [
{value: '00301', label: '西安市', isLeaf: true},
{value: '00302', label: '延安市', isLeaf: true},
]},
]
// isLeaf : 是否为子节点
// children : 含有子节点
我们将文档建立在项目静态文件资源目录中。然后在全局(具体根据数据而定)方法中创建一个Promise获取方法:
getCity() {
const url = './assets/static_data/city.json';
return new Promise((resolve, reject) => {
if (localStorage.getItem('cityList')) {
// 每登入系统则存储一次
resolve(JSON.parse(localStorage.getItem('cityList')));
return;
}
this.http.get(url).subscribe(
data => {
localStorage.setItem('cityList', JSON.stringify(data));
resolve(data);
}
);
});
}
定义好之后,其他页面需要我们可以随时调用。
下面就是城市json文件在本地,那么数据库不存在城市相关查询,仅保存了城市的value值(编码),如果我们在查询后获取后端返回的数据编码(如上述json文件中的“00301”),我们就需要通过管道将其转换为可读。
继上述,这时就需要创建一个管道 如: ng g p service/region --skipTests
命令创建一个'region'(这里随便命名了下...)管道。
进入刚刚创建的region管道文件,引入我们获取城市的定义文件,例如:
import { Pipe, PipeTransform } from '@angular/core';
import { GlobalFunService } from '../service/global-fun.service';
...
cityList: any;
constructor(
private globalFun: GlobalFunService,
) {}
/** 处理方法 */
returnIt(code, cityList) {
for (const item of cityList) {
if (item.value === code) {return item; }
if (item.children) {
const child = this.returnIt(code, item.children);
if (child) {return child; }
}
}
}
async transform(value: any, ...args: any[]) {
// 获取城市列表
this.cityList = await this.globalFun.getCity();
// 通过编码输入查找对应的城市名称将其返回
return value ? this.returnIt(value, this.cityList)['label'] : '';
}
...
这样,我们就创建了一个城市编码转换的管道。
组件中我们直接可以对其应用,如:查询返回数据信息中包含城市编码"00301",我们就可以:
{{item.cityCode | region | async}}
则可返回"00301"对应城市"西安市"(上述示例json)。
更新于2020-05-07
TS中使用自定义管道
import { RegionPipe } from './pipe/region.pipe';
@Component({
selector: '***',
templateUrl: '***.html',
styleUrls: ['./***.component.css'],
providers: [RegionPipe],
})
constructor(
private region: RegionPipe,
) { }
若将编码转为可读字符串,则:
data['list'].forEach(item => {
item.cityName = this.region.transform(item.disId);
});
仅这样,定义的cityName会为:cityName: ZoneAwarePromise
因此和HTML中一样需要 async
与 await
:
data['list'].forEach(async item => {
item.cityName = await this.region.transform(item.disId);
});
这样cityName方可正常显示。