Angular响应式表单中使用PatchValue将文件上传的Base64字符串赋值给FormGroup属性时报错
看起来你遇到的这个DOMException错误,大概率是因为FileReader对象或者FormGroup的状态出了问题——要么是FileReader被提前垃圾回收了,要么是组件销毁后回调还在执行,导致操作了已经不可用的对象。我给你几个针对性的解决思路和修改后的代码:
第一步:确保FormGroup的file控件已正确初始化
首先要确认你的FormGroup里确实包含了file这个表单控件,比如在组件的初始化逻辑(比如ngOnInit)里要这样定义:import { FormBuilder, FormGroup } from '@angular/forms'; // 组件类内 formGroup!: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit(): void { this.formGroup = this.fb.group({ file: [''] // 初始化一个空字符串的控件,确保patchValue时有对应的目标 }); }这是基础前提,如果没有初始化这个控件,patchValue时也可能触发异常,先排除这个问题。
第二步:修改FileReader的使用方式,避免被提前回收
你之前把FileReader定义成了onFileChange方法里的局部变量,在某些情况下,浏览器的垃圾回收机制可能会在回调触发前就回收这个对象,导致回调执行时reader已经不可用。建议把它改成组件的属性:// 组件类内定义FileReader属性 private fileReader: FileReader = new FileReader(); onFileChange(event: Event) { const input = event.target as HTMLInputElement; if (input.files && input.files.length > 0) { const [file] = input.files; // 先终止之前可能还在进行的读取操作,避免冲突 this.fileReader.abort(); this.fileReader.onload = () => { // 先检查formGroup是否还存在(防止组件已销毁的情况) if (this.formGroup) { this.formGroup.patchValue({ file: this.fileReader.result as string }); // 可选:更新控件的状态,触发验证逻辑 this.formGroup.get('file')?.updateValueAndValidity(); } }; this.fileReader.readAsDataURL(file); } }第三步:组件销毁时清理FileReader,防止内存泄漏和无效回调
在组件销毁的时候,记得终止FileReader的操作,避免它在组件销毁后还执行回调,导致操作已经不存在的FormGroup:import { OnDestroy } from '@angular/core'; // 组件类实现OnDestroy接口 export class YourComponent implements OnDestroy { // ... 其他代码 ngOnDestroy(): void { // 终止FileReader的读取操作 this.fileReader.abort(); } }
这个An attempt was made to use an object that is not, or is no longer, usable错误的本质是:你在回调里尝试使用的对象(要么是FileReader的result,要么是FormGroup)已经处于不可用状态了——可能是FileReader被GC回收,也可能是组件已经被销毁但回调还在执行。上面的修改就是从这两个点入手,确保对象的可用性和回调的安全性。
备注:内容来源于stack exchange,提问作者ckeedee

