JavaScript FileReader异步问题:处理邮件附件File数组时函数提前返回如何解决
解决方案
问题原因
FileReader 的读取逻辑是异步执行的,外层同步函数不会等待 onload 回调触发就会提前返回结果,且事件回调的返回值无法透传到外层函数的返回值中,因此你拿到的返回对象里 attachments 数组为空。
改造方案
核心是将整个读取逻辑包装为 Promise,让函数返回异步结果:
步骤1:封装单个文件的读取逻辑
写一个辅助函数,把单个File读取为Attachment的逻辑包装成Promise:
function readAttachment(file: File): Promise<Attachment> { return new Promise((resolve, reject) => { const newAttachment = new Attachment(); newAttachment.dateiname = file.name; newAttachment.dateityp = file.type; newAttachment.size = file.size; const reader = new FileReader(); reader.onload = (event) => { newAttachment.fileData = event.target.result.toString(); resolve(newAttachment); }; // 增加错误处理,避免读取失败时整个流程卡住 reader.onerror = (error) => reject(error); reader.readAsText(file); }); }
步骤2:改造getMessage为异步函数
用Promise.all等待所有附件读取完成后,再组装返回message对象:
async function getMessage(message: NewMessage, attachments: File[]): Promise<Message> { // 生成所有附件的读取Promise数组,并发执行读取 const attachmentPromises = attachments.map(file => readAttachment(file)); // 等待所有附件读取完成 const loadedAttachments = await Promise.all(attachmentPromises); // 把读取完成的附件批量添加到message message.attachments.push(...loadedAttachments); return message; }
步骤3:调用方式调整
因为现在getMessage返回的是Promise,调用的时候需要用await或者.then()接收最终结果:
// 用法1:在async函数内使用await async function sendEmail() { const initMessage = new NewMessage(/* 你的消息初始化参数 */); const attachmentFiles = /* 你拿到的附件File数组 */; const finalMessage = await getMessage(initMessage, attachmentFiles); // 此时finalMessage的attachments已填充完成,可执行后续发送逻辑 } // 用法2:使用.then链式调用 getMessage(initMessage, attachmentFiles) .then(finalMessage => { // 后续发送逻辑 }) .catch(error => { // 处理文件读取异常 });
补充说明:如果你的附件包含图片、压缩包等非文本文件,
readAsText会导致文件损坏,可根据后端接收格式要求,将读取方法替换为readAsDataURL或者readAsArrayBuffer。
内容的提问来源于stack exchange,提问作者user1107888
相关产品推荐
相关产品推荐

