异步管道引用导致无限循环

时间:2021-07-21 02:03:21

标签: angular rxjs

我正在尝试从浏览器文件对象列表中显示图像。该模板有一个表格,其中包含以下 tr 元素:

      <tr *ngFor="let file of files">

        <td>{{ file.name }}</td>
        <td>{{ file.type }}</td>
        <td>{{ file.size | number }}</td>
        <td>
          <ng-container *ngIf="getFile(file) | async as dataURL">
            <img src="{{ dataURL }}">
          </ng-container>
        </td>
        <td>
          <button type="button" mat-button (click)="clickRemove(file)">Remove</button>
        </td>

      </tr>

在组件中,getFile() 函数返回一个简单的 Observable,如下所示:

  getFile(file: File): Observable<string> {
    console.log('getFile called for a new Observable', file.name);
    const obs = new Observable<string>(
      subscriber => {
        const reader = new FileReader();
        console.log('getFile got subscribed to!');
        reader.addEventListener("load", ev => {
          console.log('getFile got the load event!', reader.result?.slice(0,200));
          subscriber.next(reader.result as string);
        });
        reader.readAsDataURL(file);
      }
    )
    return obs;
  }

目的是当 Observable 被订阅时,它会去读取 File 所代表的数据 blob,然后返回一个字符串作为 img 元素显示的数据 URL。 console.log 语句表明 1) 它正在订阅,2) 它从 FileReader 获取事件,然后在 subscriber.next() 调用中返回结果。

结果是无限循环。即使表中有一行,我也会无限重复调用 getFile() 以获取同一个文件,然后订阅返回的 Observable,然后再次读取该文件并返回一个新的 DataURL。

谁能帮我指出循环的位置?我怀疑问题在于 Angular 的更改检测逻辑正在执行此操作,但如果是这种情况,我不知道如何诊断或修复它。

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

*ngIf 有什么作用?

通俗地说,表达式的计算是为了确定是否应该将元素插入到 DOM 中。每次 angular “怀疑”潜在值可能发生变化时,都会再次评估该表达式。

简短:ngIf 表达式将被评估多次。

这会创建您的 DataURL 洪流。

也许只是使用...

<img [src]="getFile(file) | async">

...虽然它与您的示例不完全相同。不同之处在于 img 元素始终插入到您的 DOM 中,无论读取(待处理)文件的结果如何。

没有有效 src 的图像将显示 alt 属性文本(如果有)。因此,如果您对此有特殊偏好,则必须调整我提出的解决方案。