首页 > 解决方案 > 有没有办法将不纯的管道转换为纯管道?

问题描述

我是 Angular 7 的新手,但我已经编写 AngularJS 几年了。我的问题是基于这样一个事实,即在管道中执行异步任务时(不一定是ajax调用,它可以是另一个异步任务),它必须被声明为不纯的。

根据Angular 文档

Angular在每个组件更改检测周期中执行一个不纯管道。不纯管道经常被调用,就像每次击键或鼠标移动一样频繁。

这些调用很多,例如,如果您在 50 行的表或列表中使用相同的管道,请尝试放置 a console.log,您会看到每个管道一次又一次地执行大量次数。不纯管道中的 ajax 调用示例:

import {Pipe, PipeTransform} from '@angular/core';
import {AnyService} from '../services/any.service';

@Pipe({
  name: 'anyAjaxCall',
  pure: false
})
export class AnyAjaxCallPipe implements PipeTransform {

  private isDataCached = false;
  private cachedData: string = null;

  constructor(private anyService: AnyService) {
  }

  transform(value: any): string {

    if (!this.isDataCached) {
      this.isDataCached = true;

      this.anyService
        .read(value)
        .subscribe((response: any) => {
          this.cachedData = response.data.name;
        }, (err: any) => {
          this.isDataCached = false;
          console.error(err);
        });
    }

    return this.cachedData;
  }

}

了解了以上内容,是否可以在异步任务完成后将管道从不纯的转换为纯的?我知道有可能将异步操作的结果保存在变量中作为缓存并避免多次执行(如上面的代码示例),但我认为告诉 Angular 我已经执行了我的异步任务,我不想再次运行它。

我不是前端方面的专家,所以欢迎任何建议。

标签: angularangular-pipe

解决方案


简短的回答:不,不可能将其从不纯的转换为纯的。但是,您的示例与官方文档中给出的示例非常相似:

import { HttpClient }          from '@angular/common/http';
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'fetch',
  pure: false
})
export class FetchJsonPipe implements PipeTransform {
  private cachedData: any = null;
  private cachedUrl = '';

  constructor(private http: HttpClient) { }

  transform(url: string): any {
    if (url !== this.cachedUrl) {
      this.cachedData = null;
      this.cachedUrl = url;
      this.http.get(url).subscribe(result => this.cachedData = result);
    }

    return this.cachedData;
  }
}

但是,对于它的价值,根据您的用例,我会将该调用移动到服务中(在角度服务中是单例)并在整个应用程序中共享结果。后来在文档中谈到为什么他们不再有过滤器或按管道排序时,它确实说

您可以放入管道并在应用程序中共享的任何功能都可以写入过滤/排序服务并注入到组件中。

同样,这取决于您的用例,但我希望这会有所帮助。


推荐阅读