如何将返回值从Promise<boolean>改为Boolean类型?
异步图片尺寸校验函数的返回值问题
场景说明
我有4个文件校验函数:
- 校验文件数量
- 校验文件总大小
- 校验文件类型
- 校验图片尺寸
原本的同步判断逻辑如下:
if( this.checkQuantityFiles(filesArr)&& this.checkTotalFilesSize(filesArr)&& this.checkType(filesArr)&& this.checkImageDimension(filesArr) )
问题代码
其中checkImageDimension因为需要加载图片,必须用异步逻辑,但现在无法返回预期的布尔值:
checkImageDimension(files:File[]):boolean{ function isValidImage(image: HTMLImageElement): boolean { return image.width < MAXLIMITWIDTH && image.height < MAXLIMITHEIGH; } function loadImage(file: File): Promise<HTMLImageElement> { return new Promise((resolve, reject) => { const image = new Image(); image.onload = () => resolve(image); image.onerror = reject; image.src = URL.createObjectURL(file); }); } async function checkArray(){ const imagePromises = files.map(loadImage); const images = await Promise.all(imagePromises); const every:Promise<boolean>=new Promise((resolve)=>{ resolve( images.every(isValidImage)) }) const result=await every.then((res)=>{ return res }) console.log(result); return result } const result= checkArray().then((result)=>{return result},()=>{ throw Error("Check array function invalid") }) return result//// I should return boolean here but i can't make boolean from Promise<boolean> }
核心困惑
- 给函数加
async后,编译器不允许返回Boolean,只能返回Promise<boolean> - 不加
async就没法用await解析Promise,拿到的始终是Promise对象而非实际布尔值 - 明明Promise已经执行完成,却始终拿不到最终的布尔结果
解决方案
1. 改造校验函数为异步函数
因为涉及图片加载这种异步操作,同步返回布尔值是不可能的——异步操作还未完成时,函数就已经执行完毕返回了。必须让checkImageDimension返回Promise<boolean>:
async checkImageDimension(files: File[]): Promise<boolean> { const isValidImage = (image: HTMLImageElement): boolean => { return image.width < MAXLIMITWIDTH && image.height < MAXLIMITHEIGH; }; const loadImage = (file: File): Promise<HTMLImageElement> => { return new Promise((resolve, reject) => { const image = new Image(); image.onload = () => { URL.revokeObjectURL(image.src); // 释放URL,避免内存泄漏 resolve(image); }; image.onerror = reject; image.src = URL.createObjectURL(file); }); }; try { const images = await Promise.all(files.map(loadImage)); return images.every(isValidImage); } catch (err) { throw new Error("图片加载或校验失败"); } }
这里简化了冗余的Promise包装,直接返回every的结果,同时添加了资源清理逻辑。
2. 改造原有的判断逻辑
同步if判断无法直接处理异步函数的结果,需要改成异步处理方式:
方式1:使用async/await(推荐)
把调用校验逻辑的函数改成async,用await等待异步校验结果:
async validateFiles(filesArr: File[]) { const isQuantityValid = this.checkQuantityFiles(filesArr); const isSizeValid = this.checkTotalFilesSize(filesArr); const isTypeValid = this.checkType(filesArr); const isDimensionValid = await this.checkImageDimension(filesArr); if (isQuantityValid && isSizeValid && isTypeValid && isDimensionValid) { // 所有校验通过,执行后续逻辑 } else { // 校验失败,处理错误 } }
方式2:使用Promise链式调用
如果无法使用async函数,可通过then链式处理异步结果:
validateFiles(filesArr: File[]) { const isQuantityValid = this.checkQuantityFiles(filesArr); const isSizeValid = this.checkTotalFilesSize(filesArr); const isTypeValid = this.checkType(filesArr); // 先做同步校验,失败直接返回 if (!isQuantityValid || !isSizeValid || !isTypeValid) { return; } this.checkImageDimension(filesArr) .then(isDimensionValid => { if (isDimensionValid) { // 所有校验通过 } else { // 尺寸校验失败 } }) .catch(err => { // 图片加载出错处理 }); }
关键原理
JS的异步操作是在事件循环中执行的,函数本身会先执行完毕返回Promise对象,直到异步操作(比如图片加载)完成后,才会把结果填充到Promise中。因此必须通过await或then等待异步结果,不可能直接同步拿到布尔值。
内容的提问来源于stack exchange,提问作者RobertcodeR
相关产品推荐
相关产品推荐

