当将canvas.toBlob与箭头函数一起使用时,为什么不触发Angular的ChangeDetection?

问题描述

我在Angular 10中有一个非常简单的组件。提交表单后,将创建并存储Blob元素的canvas

因此onSubmit()函数的相关部分看起来像这样:

onSubmit(): void {
  const canvas: HTMLCanvasElement = getCanvas();

  canvas.toBlob((blob: Blob) => {
    this.service.create(blob).pipe(first()).subscribe((response: boolean) => {
      this.isSuccessful = response;
    });
  },'image/png',1);
}

问题是isSuccessful已更改,但这些更改未反映在 模板。

所以我要做的是使用ChangeDetectorRef手动触发变更检测:

onSubmit(): void {
  const canvas: HTMLCanvasElement = getCanvas();

  canvas.toBlob((blob: Blob) => {
    this.service.create(blob).pipe(first()).subscribe((response: boolean) => {
      this.isSuccessful = response;
      this.cdr.detectChanges();
    });
  },1);
}

现在,这可行。 但是为什么在这里需要它?在所有其他情况下,当我使用这种箭头功能时,就不需要更改检测器。 toBlob()方法似乎与此不同。

PS:当cdr方法不在service.create()方法之外时,也不需要toBlob()

解决方法

因为canvas.toBlobAngular Zone之外执行回调,所以未触发更改检测。调用ChangeDetectorRef.detectChanges的另一种方法是确保使用NgZone.run在Angular区域内执行代码:

import { NgZone } from '@angular/core';
...

constructor(private ngZone: NgZone) { }

canvas.toBlob((blob: Blob) => {
  this.ngZone.run(() => {
    // Run the code here
  });
},'image/png',1);

有关演示,请参见this stackblitz