使用FileReader读取上传图片时外部console.log值不匹配如何解决
问题原因
FileReader的readAsDataURL以及对应的onload回调是异步执行的:你调用reader.readAsDataURL(file)之后,浏览器不会等待文件读取完成,会直接继续往下执行后面的console.log("out", this.imgArrayy)代码,这时候onload回调还没触发,this.imgArrayy还没被赋值为当前选中文件的字节数组,就会出现你看到的现象:
- 第一次选图:
out打印时this.imgArrayy还没被赋值过,所以输出undefined,等onload触发后才给this.imgArrayy赋第一张图的值 - 第二次选图:
out打印时onload还没处理第二张图,this.imgArrayy存的还是第一次赋值的第一张图结果,所以打印上一张的字节数组,等onload触发后才更新为第二张的结果
解决方案
方案1:直接在onload回调中处理业务逻辑
所有需要用到当前图片字节数组的操作,都放到onload回调内部执行,就能保证拿到的是当前最新的结果:
upload(files: any) { const file = files.files[0]; if (!file) return; const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (event) => { this.url = reader.result as string; const base64Index = this.url.indexOf(';base64,') + ';base64,'.length; const base64 = this.url.substring(base64Index); const raw = window.atob(base64); const rawLength = raw.length; const imgArray = new Uint8Array(new ArrayBuffer(rawLength)); for (let i = 0; i < rawLength; i++) { imgArray[i] = raw.charCodeAt(i); } this.imgArrayy = imgArray; console.log("当前图片字节数组:", this.imgArrayy); // 所有需要用到imgArrayy的业务逻辑都写在这里 // 比如上传请求、本地预览等操作 }; }
方案2:用Promise封装实现async/await调用
如果需要在upload函数外部拿到结果,可以把文件读取逻辑封装成Promise,调用时用await等待异步操作完成:
// 封装文件读取为字节数组的通用方法 getFileByteArray(file: File): Promise<Uint8Array> { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (event) => { const url = reader.result as string; const base64Index = url.indexOf(';base64,') + ';base64,'.length; const base64 = url.substring(base64Index); const raw = window.atob(base64); const rawLength = raw.length; const imgArray = new Uint8Array(new ArrayBuffer(rawLength)); for (let i = 0; i < rawLength; i++) { imgArray[i] = raw.charCodeAt(i); } resolve(imgArray); }; reader.onerror = (error) => reject(error); }); } // 改造upload方法为异步方法 async upload(files: any) { const file = files.files[0]; if (!file) return; this.imgArrayy = await this.getFileByteArray(file); this.url = URL.createObjectURL(file); // 也可以直接用这个方法生成预览链接,不需要自己转base64 console.log("out", this.imgArrayy); // 这里就能拿到当前最新的字节数组了 // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者Valkyrie_30
相关产品推荐
相关产品推荐

