JavaScript 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 操作,页面渲染完成。
解决办法
1.替换 Alert() 函数 首先我们考虑替换掉 alert 函数的功能。我们可以考虑 Bootstrap 的 modal 模块,Bootstrap 在绝大多数网站上都在应用,而多引入一个 modal 模块也不会有多大影响。我们使用 modal 构造一个弹出对话框的样子,使用 modal 的 modal('toggle')/modal('show')/modal('hide') 方法可以很方便地控制 modal 的显隐。
2.使用 setTimeout() 函数,使用它,可以延迟执行某些代码。