Angular 管道之异步数据读取转换

这篇文章由 DeathGhost 编辑,发布于

归类于 Angular » 👋分享到微博 当前评论 1 条。

async 管道会订阅一个 Observable 或 Promise,并返回它发出的最近一个值。 当新值到来时,async 管道就会把该组件标记为需要进行变更检测。当组件被销毁时,async 管道就会自动取消订阅,以消除潜在的内存泄露问题。

每个应用开始的时候差不多都是一些简单任务:获取数据、转换它们,然后把它们显示给用户。

一旦取到数据,你就可以把它们原始值的 toString 结果直接推入视图中。 但这种做法很少能具备良好的用户体验。

例如,在项目应用中前端通过请求后端程序接口,往往会返回一些数字、字符或原始数据形式标识,常见的日期这类信息,通常会直接显示原始数据,用户可读性很差Sun Sep 22 2019 00:00:40 GMT 0800 (中国标准时间)等等诸如此类的数据信息,用户阅读起来比较困难,因此我们需要将其转换为2019-09-22这般方可。

这种情形下,在Angular中我们就需要使用管道对其转换,进而达到用户可读数据。更多管道信息,这里不多解释说明,下面看看关于Angular中异步数据信息管道的使用。

Angular 异步管道
Angular 异步管道 AsyncPipe

示例需求:通过请求获取本地城市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中一样需要 asyncawait

data['list'].forEach(async item => {
  item.cityName = await this.region.transform(item.disId);
});

这样cityName方可正常显示。


Angular AsyncPipe async Promise Observable 管道 异步 异步管道 数据转换 格式转换

上一篇:

下一篇: