Angular中图片上传时image.onload滞后,宽高获取为undefined求助
问题描述
我正在使用Angular开发图片输入功能,会移除插入图片的名称、大小等信息。目前遇到的问题是:上传图片时需要获取其宽高,但上传操作会先于获取图片信息的函数执行,导致宽高值为undefined,即上传函数比image.onload先执行。以下是我的Component.ts中的detectFiles代码:
detectFiles(event) { if (files.length < 8) { for (let index = 0; index < files.length; index++) { this.items.push(item); const reader = new FileReader(); reader.onload = (e: any) => { item.url = e.target.result; const image = new Image(); image.src = e.target.result; image.onload = function () { item.sizeH = image.width; }; } formData.append('file', files[index]); reader.readAsDataURL(files[index]); } } }
请问有人知道原因吗?
解决方案
嘿,这个问题我之前也碰到过!核心原因是异步操作的执行顺序问题:
FileReader.onload和Image.onload都是异步回调事件——它们不会在调用后立刻执行,而是要等文件读取完成、图片加载完成后才会触发。但你当前代码里的formData.append('file', files[index])是同步执行的,循环里这个append操作会马上跑完,而此时image.onload的回调还没来得及触发,item.sizeH自然就是undefined了。
想要解决这个问题,关键是把依赖图片宽高的操作(比如formData添加文件、后续上传请求)放到image.onload的回调内部,确保宽高获取完成后再执行上传相关逻辑。
修改后的基础版本代码
detectFiles(event) { const files = event.target.files; // 补充原代码遗漏的文件获取逻辑 if (files.length < 8) { for (let index = 0; index < files.length; index++) { const item = {}; // 补充原代码遗漏的item初始化 this.items.push(item); const reader = new FileReader(); reader.onload = (e: any) => { item.url = e.target.result; const image = new Image(); image.src = e.target.result; image.onload = () => { item.sizeH = image.width; // 等宽高获取完成后,再执行文件添加和上传逻辑 formData.append('file', files[index]); // 这里可以调用你的上传API,比如 this.uploadImage(formData) }; } reader.readAsDataURL(files[index]); } } }
更优雅的Promise+async/await版本
如果想让异步逻辑更清晰,也可以把图片加载、文件读取封装成Promise,用async/await控制执行顺序:
// 封装获取图片宽高的Promise函数 getImageDimensions(imageSrc: string): Promise<{width: number, height: number}> { return new Promise((resolve) => { const image = new Image(); image.src = imageSrc; image.onload = () => { resolve({width: image.width, height: image.height}); }; }); } // 修改detectFiles为异步函数 async detectFiles(event) { const files = event.target.files; if (files.length < 8) { for (let index = 0; index < files.length; index++) { const item = {}; this.items.push(item); // 把FileReader读取也封装成Promise const readerResult = await new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e: any) => resolve(e.target.result); reader.readAsDataURL(files[index]); }); item.url = readerResult; // 等待图片宽高获取完成 const dimensions = await this.getImageDimensions(readerResult as string); item.sizeH = dimensions.width; // 现在可以安全执行上传相关操作 formData.append('file', files[index]); // this.uploadImage(formData); } } }
这样就能确保所有依赖图片宽高的操作,都在宽高值确定后才执行,不会再出现undefined的问题啦!
内容的提问来源于stack exchange,提问作者user11052170
相关产品推荐
相关产品推荐

