如何等待.onload事件完成后批量校验多张图片分辨率再执行上传
解决方案
核心问题是Image.onload属于异步回调事件,原同步实现的校验方法不会等待回调执行就直接返回初始值,导致逻辑完全失效。我们需要将校验逻辑改造为异步方案,用Promise处理所有图片的加载校验任务,等待所有校验结果返回后再执行后续操作。
改造步骤
- 将
verifyFilesResolution改造为返回Promise<boolean>的异步方法,每张图片的校验都封装为独立Promise,支持全部加载完成后返回结果,也可检测到第一张不符合规则的图片时直接中断校验 - 调用校验方法的
prepareFilesList改造为异步方法,用await等待校验结果返回后再执行上传或抛错逻辑
完整实现代码
// 校验方法返回Promise,resolve(true)代表存在分辨率不符合的错误,resolve(false)代表全部校验通过 async verifyFilesResolution(files: File[]): Promise<boolean> { if (!files || files.length === 0) return false; // 把每个文件的校验包装成独立Promise const verifyPromises = files.map(file => { return new Promise<boolean>((resolve) => { const img = new Image(); const objectUrl = window.URL.createObjectURL(file); img.onload = () => { // 加载完成后释放objectUrl,避免内存泄漏 window.URL.revokeObjectURL(objectUrl); // 分辨率不符合要求返回true resolve(img.width <= 800 || img.height <= 600); }; img.onerror = () => { window.URL.revokeObjectURL(objectUrl); // 图片加载失败也判定为无效文件 resolve(true); }; img.src = objectUrl; }); }); // 等待所有校验任务执行完成 const results = await Promise.all(verifyPromises); // 只要有一个结果为true,说明存在不符合要求的图片 return results.some(isInvalid => isInvalid); } // 调用方改造为async异步方法 async prepareFilesList(files: File[]) { const hasInvalidImage = await this.verifyFilesResolution(files); if (!hasInvalidImage) { this.selectedFiles = files; this.uploadFiles(); } else { return this.toastr.error('Image must be at least 800x600 .'); } }
可选优化方案
如果需要检测到第一张不符合要求的图片时就立即返回结果,不需要等待所有图片加载完成,可以调整为以下实现:
async verifyFilesResolution(files: File[]): Promise<boolean> { if (!files || files.length === 0) return false; const verifyPromises = files.map(file => { return new Promise<void>((resolve, reject) => { const img = new Image(); const objectUrl = window.URL.createObjectURL(file); img.onload = () => { window.URL.revokeObjectURL(objectUrl); if (img.width <= 800 || img.height <= 600) { // 遇到不符合的直接reject,中断后续校验 reject(); } resolve(); }; img.onerror = () => { window.URL.revokeObjectURL(objectUrl); reject(); }; img.src = objectUrl; }); }); try { // 所有Promise都resolve代表全部符合要求 await Promise.all(verifyPromises); return false; } catch { // 有任意一个reject代表存在不符合的图片 return true; } }
内容的提问来源于stack exchange,提问作者Stefan T
相关产品推荐
相关产品推荐

