如何用async/await实现文件选择对话框的异步调用?
修复Async/Await版文件选择对话框的取消逻辑问题
你的代码存在三个核心问题:
- 未返回创建的Promise,导致
await无法获取结果 resolveCallback仅返回文件列表,未调用Promise的resolve/reject方法- 未处理用户取消选择的场景,导致Promise永远处于pending状态
以下是修正后的完整代码:
async function browseForFile(acceptedTypes: string, multiple?: boolean): Promise<FileList> { return new Promise((resolve, reject) => { const input = document.createElement("input"); input.type = "file"; input.accept = acceptedTypes; input.multiple = !!multiple; // 清理资源:移除事件监听并删除DOM元素 const cleanup = () => { input.removeEventListener("change", onChange); document.removeEventListener("focus", onFocus); input.remove(); }; // 文件选择完成事件处理 const onChange = () => { if (input.files.length > 0) { resolve(input.files); } else { reject(new Error("No files selected")); } cleanup(); }; // 对话框取消事件处理:通过document焦点恢复判断 const onFocus = () => { setTimeout(() => { if (input.files.length === 0) { reject(new Error("File selection cancelled")); cleanup(); } }, 100); }; input.addEventListener("change", onChange); // 仅监听一次focus事件,避免重复触发 document.addEventListener("focus", onFocus, { once: true }); input.click(); }); }
使用示例
try { const files = await browseForFile("text/*"); // 转换为数组方便操作 const fileArray = Array.from(files); console.log("选中的文件:", fileArray); } catch (error) { console.log(error.message); // 取消选择时输出"File selection cancelled" }
关键说明
- 必须在用户交互上下文(如按钮点击事件)中调用该函数,否则浏览器会因安全限制阻止文件选择框弹出
- 通过监听
document.focus事件判断对话框关闭,兼容主流浏览器的取消场景 - 新增
cleanup函数清理事件监听和DOM元素,避免内存泄漏
内容的提问来源于stack exchange,提问作者1.21 gigawatts
相关产品推荐
相关产品推荐

