alert()是同步阻塞式API,无法异步调用;实现类似效果需用自定义弹窗+Promise封装,注意可访问性、防重入及DOM清理。

HTML原生alert()根本不能异步调用
直接说结论:alert() 是同步阻塞式 API,浏览器会暂停 JS 执行直到用户点击确定。所谓“异步调用”是误解——你没法用 await alert('xxx') 或给它加 Promise 包装来真正解耦执行流。
常见错误现象:写 async function foo() { await alert('hi'); console.log('done'); },结果 console.log 立刻执行,alert 还没弹出——因为 alert 本身不返回 Promise,await 对它无效,等同于 await undefined。
想实现“类似异步效果”,必须用自定义弹窗 + Promise 封装
核心思路:用 HTML/CSS/JS 自建一个非阻塞的对话框元素,点击按钮后 resolve/reject 对应的 Promise,让调用方能用 await 等待用户操作。
实操建议:
- 创建一个带遮罩层和确认/取消按钮的 ,初始
display: none或用 CSS class 控制显隐- 封装函数如
showConfirm(message),内部返回new Promise((resolve, reject) => {...})- 确认按钮绑定
resolve(true),取消或关闭按钮绑定reject(false)或resolve(false)(按业务定)- 务必手动调用
element.remove()或清空内容,避免重复点击叠加 DOM 节点示例关键片段:
function showConfirm(msg) { return new Promise((resolve) => { const modal = document.createElement('div'); modal.innerHTML = ` <div class="overlay"> <div class="modal"> <p>${msg}</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20d3191a227.jpg" alt="DeepBI DHTML 页面生成器" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="overflowclass">DeepBI DHTML 页面生成器</a> <p class="overflowclass">生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur</p> </div> <a rel="nofollow" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <button id="confirm-yes">确定</button> <button id="confirm-no">取消</button> </div> </div> `; document.body.appendChild(modal); modal.querySelector('#confirm-yes').onclick = () => { resolve(true); modal.remove(); }; modal.querySelector('#confirm-no').onclick = () => { resolve(false); modal.remove(); }; }); }使用时注意事件循环与 DOM 状态
即使封装成 Promise,也要小心调用时机。比如在
fetch回调里直接await showConfirm(...)没问题;但在setTimeout(() => { await showConfirm(...) }, 0)中会报语法错误——await只能在async函数内使用。容易踩的坑:
- 忘记给自定义弹窗加
tabindex="-1"和focus(),导致键盘用户无法操作,可访问性失败 - 未禁用背景滚动(
document.body.style.overflow = 'hidden'),弹窗出现时页面仍可滚动 - 多个
showConfirm连续调用,未做防重入处理,导致弹窗层叠或 Promise 状态混乱 - 没监听
Escape键关闭,或没处理点击遮罩层关闭逻辑,交互不完整
真需要系统级提示?考虑 Notification API 而非弹窗
Notification.requestPermission()和new Notification()是异步的,且不打断用户操作,适合轻量状态提醒(如“保存成功”)。但它受浏览器权限限制,首次需用户授权,且 Chrome 等桌面端默认静音、不聚焦窗口。适用场景有限:仅文本+图标,无按钮,无法获取用户“确认/取消”反馈。别指望用它替代确认类交互。
复杂点在于权限状态管理——
Notification.permission可能是"granted"、"denied"或"default",后者需主动调用requestPermission()并等待 Promise 结果,且用户拒绝后无法再次触发授权请求(除非手动进设置)。 - 封装函数如
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










