详解JavaScript Alert函数执行顺序问题

作者:木棉

时间:2026-10-24

浏览:247

本文深入解析JavaScript中alert、confirm等阻塞函数导致页面DOM渲染滞后的现象。通过分析单线程模型与事件循环机制,阐明同步代码优先执行原理,并提供替换自定义对话框及使用setTimeout异步化两种解决方案,帮助开发者避免“回调地狱”并优化用户交互体验。

文章目录

问题

日前编写 JavaScript 构建 HTML 页面时遭遇一异常现象:

期望功能为借助 confirm() 弹窗引导用户选定不同需求,每次选定后将结果暂存并输出至页面,末次选定完毕后统一将选项传至后端处理。代码示例如下:


var step1 = confirm("exec step1?");
$('#result').html($('#result').html() + "\n" + step1);
var step2 = confirm("exec step2?");
$('#result').html($('#result').html() + "\n" + step2);
var step3 = confirm("exec step3?");
$('#result').html($('#result').html() + "\n" + step3);

send(step1, step2, step3);

然代码执行后显现:每次 confirm 函数执行完毕且用户选定选项后,页面未即时刷新,step1、step2 结果未实时更新至页面,直至最后一步方与 step3 一同展示。

后续试验 alert() 与 prompt() 这两个与 confirm 类似的对话框函数,情形均同此,皆会跳过页面渲染而先行执行。

此时,尚存更离奇状况,向某 div 赋值后立即 alert 该 div 内容,可见 alert 显示正确内容,而 div 内内容未更新,且持续阻塞直至点击确定。

如图:

问题

alert、prompt、confirm 三函数类似,下文以 simplest alert 为例阐述。

分析

解决此问题前需明晰其成因,探究成因需从 JavaScript 线程模型入手。

JavaScript 引擎以单线程运行,浏览器始终仅且仅有一个线程执行 JavaScript 程序,初衷在于降低 DOM 等共享资源冲突。然而单线程必面临一问题,即某段代码阻塞将致使后续所有任务延迟。又因 JavaScript 常需操作页面 DOM 及发送 HTTP 请求,此类 I/O 操作耗时通常较长,一旦阻塞,将给用户带来极差的使用体验。

由此衍生出事件循环(event loop),JavaScript 将部分异步操作或含 I/O 阻塞的操作全数置入事件队列,先顺序执行同步 CPU 代码,待 JavaScript 引擎无同步代码、CPU 空闲时再读取事件队列中的异步事件依次执行。

此类事件涵盖:

  • setTimeout() 设定的异步延迟事件;
  • DOM 操作相关如布局与绘制事件;
  • 网络 I/O 如 AJAX 请求事件;
  • 用户操作事件,诸如鼠标点击、键盘敲击。

解决

明晰原理后,解决此问题便有了方向,我们来剖析此问题:

1.因页面渲染属 DOM 操作,会被 JavaScript 引擎置入事件队列;

2.alert() 为 window 内置函数,被视为同步 CPU 代码;

3.JavaScript 引擎优先执行同步代码,alert 弹窗先现;

4.alert 具特殊阻塞性质,JavaScript 引擎执行被阻塞;

5.点击 alert “确定”,JavaScript 解除阻塞,执行完同步代码后,再读取事件队列中的 DOM 操作,页面渲染完成。

由上述缘由,致使离奇的“Alert执行顺序问题”。我们无法将页面渲染转为同步操作,故仅能将 alert() 变为异步代码,从而得以在页面渲染后执行。

针对此解决方向,我们具备两种可用方法:

替换 Alert() 函数

首先考量替换 alert 函数功能。实则多数情形下替换 alert 并非因其执行顺序不符预期,而是因其外观过于简陋,且不支持各类美化,可想象在特定主题网站中突兀弹出灰色单调对话框是何等不协调。

此情形可考虑 Bootstrap 的 modal 模块,Bootstrap 在绝大多数网站均有应用,多引入一 modal 模块影响甚微。我们利用 modal 构建弹出对话框样式,借助 modal 的 modal('toggle')/modal('show')/modal('hide') 方法可便捷控制 modal 显隐。

替换对话框后,尚需解决后续代码执行问题。使用 alert 函数时,点击确定后代码仍继续执行,而使用自定义对话框则无此功能,需考量将后续代码绑定于对话框点击按钮,此即需运用 DOM 的 onclick 属性,我们将后续函数内容抽离为新函数,于弹出对话框后将此函数绑定至按钮的 onclick 事件即可。

此处尚需注意,新函数内应包含关闭 modal 对话框内容。

当然,我们还可进一步优化,抽象出一用于弹出对话框的函数以替代 alert 函数,示例如下:


window.alert = function (message, callbackFunc) {
    $('#alertContent').html(message);
    $('#modal').show();
    $('#confirmButton').onclick(function () {
        $('#modal').hide();
        callbackFunc();
    });
};

如此,我们在需弹出框时调用新 alert 函数,并传入 callbackFunc,于其中处理后续事宜即可。

setTimeOut函数

当然,并非所有人都愿以新对话框替换 alert 函数对话框,总觉上述方法不够优雅,对此,我们可采另法解决此问题。

前端开发者对 setTimeout() 此函数应不陌生,使用它,可延迟执行某些代码。而对于延迟执行的代码,JavaScript 引擎总将这些代码置入事件队列,再去检查是否已到执行时间,再适时执行。代码进入事件队列,即意味着代码变为与页面渲染事件同等异步。因事件队列有序,若用 setTimeout 延时执行,便可实现在页面渲染后执行 alert 功能。

setTimeout 函数原型为 setTimeout(code, msec),code 为需变为异步的代码或函数,msec 为延时时间,单位为毫秒。此处无需其延时,仅需其变为异步即可,故可将 msec 设为 0;

同样,alert 之后代码亦需处理,将其与 alert 一同放入 setTimeout 中异步执行。如此,代码即变为 setTimeout("alert('msg');doSomething();", 0),若觉代码不够美观或字符串难处理,可将后续代码封装为一函数置于 doSomething() 中即可。

小结

上述两个解决方案中,皆利用了 JavaScript 的回调函数,前者将函数作为 alert 参数并绑定至 DOM 的 onclick 事件,后者使用 setTimeout 将函数转为异步执行。JavaScript 的回调函数确甚强大,使用亦简便,然隐含一问题,即回调嵌套问题,单层回调易理解,但若需实现如我需求般,有多 alert 与页面渲染轮流执行情形,所面临者恐为“回调地狱”,onclick 事件绑定内函数又需嵌套绑定 onclick 函数,setTimeout 内尚需另一 setTimeout 语句,一旦出问题,排查便较麻烦。

以上即为详解JavaScript Alert函数执行顺序问题之详细内容,更多关于JavaScript Alert函数执行顺序问题之资料请关注本站其它相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章