我正在尝试从浏览器文件对象列表中显示图像。该模板有一个表格,其中包含以下 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 的更改检测逻辑正在执行此操作,但如果是这种情况,我不知道如何诊断或修复它。
感谢任何帮助。
答案 0 :(得分:0)
*ngIf 有什么作用?
通俗地说,表达式的计算是为了确定是否应该将元素插入到 DOM 中。每次 angular “怀疑”潜在值可能发生变化时,都会再次评估该表达式。
简短:ngIf 表达式将被评估多次。
这会创建您的 DataURL 洪流。
也许只是使用...
<img [src]="getFile(file) | async">
...虽然它与您的示例不完全相同。不同之处在于 img 元素始终插入到您的 DOM 中,无论读取(待处理)文件的结果如何。
没有有效 src 的图像将显示 alt 属性文本(如果有)。因此,如果您对此有特殊偏好,则必须调整我提出的解决方案。