角度绑定到视图上的函数会导致对数据服务的无限调用

Posted

技术标签:

【中文标题】角度绑定到视图上的函数会导致对数据服务的无限调用【英文标题】:Angular Binding to a function on the view results to infinite calls to the data service 【发布时间】:2016-08-10 14:01:53 【问题描述】:

我正在尝试将图像的 src 属性绑定到 ngFor 指令中,如下所示:

<div *ngFor="imageId of imageIds">
  <img [attr.src]="imageSrc(imageId)" >
</div>

组件内部的imageSrc 方法如下所示:

imageSrc(imageId: string)
  var hostUrl = "http://192.168.0.101:3000/";
  var imageUrl = hostUrl+"images/"+imageId;
  var imgSrc = "";

  this._imageService.getImage(imageId)
  .subscribe(image => 
    imgSrc = hostUrl + image.url
   );
  return imgSrc;

Injectable ImageService 中的getImage 函数如下所示:

getImage(id: string) 
  var _imageUrl = "http://192.168.0.101:3000/images/"+id;
  return this.http.get(_imageUrl)
  .map(res => <Image>res.json().data)
  .catch(this.handleError)

问题是,只有两个 imageIds *ngFor 指令按预期呈现两个列表项(但没有显示图像),但是对数据服务的调用并没有停止,它获取了两个图像并且在应用程序崩溃之前似乎是一个无限循环。我做错了什么?

【问题讨论】:

【参考方案1】:

我认为这与*ngFor 无关。如果你从视图绑定到一个函数,那么每次 Angular 运行变化检测时都会调用这个函数,默认情况下,在你页面上发生的每个事件上都会调用这个函数。

devMode(与 prodMode 相反)中,更改检测甚至对每个事件运行两次。

将结果存储在属性中并绑定到该属性,或者如果输入参数 (id:string) 自上次调用以来未更改,则至少在后续调用中从您的函数返回缓存结果。

例如https://***.com/a/36291681/217408中所示

【讨论】:

所以我认为绑定到 getter 也不是一个好主意? 如果 getter 不做像 get fullName():string return this.givenName + ' ' + this.familyName; 这样的昂贵工作,它可能没问题。但是更改检测对字段非常有效,因此最好将givenNamefamilyName 实现为getter+setter,其中fullName 每次调用setter 时都会更新。绝对不行的是像get style() return 'background-color': 'red'; 这样的getter,因为这里每次更改检测运行时,都会返回一个新的对象实例(你甚至应该在开发模式下得到一个异常),... ... 也不要做任何比上述字符串连接更昂贵的工作。

以上是关于角度绑定到视图上的函数会导致对数据服务的无限调用的主要内容,如果未能解决你的问题,请参考以下文章

Js中的防抖与节流

角度变量未绑定到视图

在异步函数上调用结果是不是会导致无限期阻塞?

无法将web api服务数据绑定到角度为2的ng2-smart-table

NodeJS - 对承诺函数的无限调用

导入自动调用函数将此绑定到window对象