JavaScript alert 函数执行顺序问题

问题


alert()弹窗总数优先于其他的代码执行:代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input id="abc">
<button id="buttons">按钮</button>

</body>
<script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
<script>
    //点击按钮给abc的input赋值然后弹窗提醒
    $("#buttons").click(function(){
        $("#abc").val('1234567890');
        alert('已经赋值完成');
    })
</script>
</html>

效果如图:

点击按钮先弹出了alert提醒。alert、prompt、confirm 三个函数都类似,接下来我们就用最简单的 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() 变为异步代码,从而才能在页面渲染之后执行。

对于这个解决方向,我们有两种方法可以使用:

1、替换 Alert() 函数,使用其他方式实现弹窗。

2、setTimeOut函数,setTimeout("alert('1234567890')", 0);

setTimeout 的函数原型为 setTimeout(code, msec),code 是要变为异步的代码或函数,msec 是要延时的时间,单位为毫秒。这里我们不需要它延时,只需要它变为异步就行了,所以可以将 msec 设置为 0;

原文地址:https://www.cnblogs.com/zhenbianshu/p/8686681.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值