<div class="test">测试内容</div>
  <script>
    $('.test').text('内容改变')
    alert($('.test').text())
    // 页面加载后首先时alert弹出,alert的内容为 ‘内容改变’,而dom此时还未发生变化,dom的内容是‘测试内容’
    // 然后会一直堵塞,直到我们点击确认,alert消失时,页面内容才会变成‘内容改变’
    // 所以alert prompt confirm等提示框都会跳过页面渲染先执行
  </script>

解决这个问题之前先了解一下它是怎么导致的,而要了解它需要从 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() 变为异步代码,从而才能在页面渲染之后执行。

解决方法:

etTimeout() 使用它,可以延迟执行某些代码。而对于延迟执行的代码,JavaScript 引擎总是把这些代码放到事件队列里去,再去检查是否已经到了执行时间,再适时执行。代码进入事件队列,就意味着代码变成和页面渲染事件一样异步了。由于事件队列是有序的,我们如果用 setTimeout 延时执行,就可以实现在页面渲染之后执行 alert 的功能了。

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

  <div class="test">测试内容</div>
  <script>
    $('.test').text('内容改变')
    setTimeout(function(){
      alert($('.test').text())
    },0)
    // 由于使用setTimeout操作,使alert被放入到事件队列 ,
    // 同时 $('.test').text('内容改变')也是在事件队列
    // 所以 dom和alert的内容都是 ‘内容改变’

alert执行时机和js线性模型 事件循环的更多相关文章

  1. Node.js 的事件循环机制

    目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...

  2. js的事件循环绑定和jQuery的隐式迭代

    js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...

  3. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...

  4. Node.js:事件循环

    ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...

  5. 浏览器中 JS 的事件循环机制

    目录 事件循环机制 宏任务与微任务 实例分析 参考 1.事件循环机制 浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图). 第一步:主线程(JS引擎线程)中执行 ...

  6. Js之事件循环(执行机制)

    js的执行机制是事件循环 什么是事件循环? js引擎在执行代码时,首先会将同步代码加入到主线程中,异步代码会放到event table中注册回调函数, 当主线程空闲之后,event table中的回调 ...

  7. js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)

    javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...

  8. JS:事件循环机制、调用栈以及任务队列

    点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...

  9. JavaScript之JS单线程|事件循环|事件队列|执行栈

    本博文基于知乎"JavaScript作用域问题?"一问,而引起了对JavaScript事件循环和单线程等概念与实践上的研究.深入理解. 一.概念 0.关键词:JavaScript单 ...

随机推荐

  1. MyBatis动态代理执行原理

    前言 大家使用MyBatis都知道,不管是单独使用还是和Spring集成,我们都是使用接口定义的方式声明数据库的增删改查方法.那么我们只声明一个接口,MyBatis是如何帮我们来实现SQL呢,对吗,我 ...

  2. 【小o地图Excel插件版】计算两点间驾车路径,获取途径道路、驾车距离、耗时等信息

    小o地图Excel插件版:一款基于Excel软件开发的地图软件,提供基于Excel表格进行地理数据挖掘.地理数据分析.地图绘制.地图图表等功能的工具类软件.具有易用.高效.稳定的特点,能够满足地理数据 ...

  3. [Go] Go的WaitGroup计数信号量

    WaitGroup是一个计数信号量,可以用来记录并维护运行的goroutine,如果WaitGroup的值大于0,Wait方法就会阻塞 调用Done方法来减少WaitGroup的值,并最终释放main ...

  4. C# 应用Excel条件格式(一)

    Excel中的条件格式功能是个十分强大且方便的功能,通过对使用条件格式功能可以在很大程度上改进表格的设计和可读性,用户可以指定单个或者多个单元格区域应用一种或者多种格式,如此一来,也在大大提高了表格的 ...

  5. C# 如何添加PPT背景(纯色背景、渐变色背景、图片背景)

    我们在创建Powerpoint文档时,系统默认的幻灯片是空白背景的,很多时候我们需要自定义幻灯片背景,以达到美观的文档效果.在下面的示例中将介绍给PowerPoint幻灯片设置背景的方法,主要包含以下 ...

  6. "PECS原则"几篇好文章

    <? extends T>和<? super T>Java 泛型中的PECS原则(copy源码样例) ​

  7. Java开发笔记(三十八)利用正则表达式校验字符串

    前面多次提到了正则串.正则表达式,那么正则表达式究竟是符合什么定义的字符串呢?正则表达式是编程语言处理字符串格式的一种逻辑式子,它利用若干保留字符定义了形形色色的匹配规则,从而通过一个式子来覆盖满足了 ...

  8. 【学习笔记】tensorflow文件读取

    目录 文件读取 文件队列构造 文件阅读器 文件内容解码器 开启线程操作 管道读端批处理 CSV文件读取案例 先看下文件读取以及读取数据处理成张量结果的过程: 一般数据文件格式有文本.excel和图片数 ...

  9. 零基础学Python--------入门篇 第1章 初始Python

    入门篇 第1章  初始Python 1.1  Pyhton 概述 1.1.1 了解 Python Python,本义是指“蟒蛇”.1989年,荷兰人Guido van Rossum发明了一种面向对象的 ...

  10. 老王说JavaDoc

    开场白说点东西: { 抓住客户的痛点.痒点.爽点,提出我们产品的核心价值. 产品定位 技术架构 以微服务为核心的前后端分离,业务积木装配式技术架构.传感器采集,物联网+互联网转换,大数据分布式.存储. ...