我想这次我真的理解了 JavaScript 的单线程机制
今天面试的时候被问到一个问题,是关于 JS 异步的。当时我脑海中闪过了一个单线程的概念,但却没有把真正的原理阐述清楚。所以回来特意重新回顾了前面单线程和异步相关的一些知识点。
虽然之前学习的时候也接触了单线程模型相关的东西,但当时理解得并不是很清楚和明白。所以这道面试题也没有给出一语中的的答案。重新阅读阮一峰的 《JavaScript 运行机制详解》和我之前写的《setTimeout 异步与回调》之后。我决定重新写一篇博客来更加白话的总结 JS 的单线程机制和异步。
重演历史 - 为什么 JS 是单线程
当我们打开一个页面,页面的 JS 会去执行。从系统层面来说,他是单线程的去执行。换句话讲系统中只有一个线程去处理整个页面的渲染(代码的执行)。为什么会这样呢?因为简单,因为 JS 很早就被发明出来了,浏览器也是。那个时候考虑的第一件事,是功能简单。试想一下如果是多线程,一个处理页面渲染 DOM 操作,另外的线程也处理,就会出现混乱。因为搞不清楚谁做了什么,做到什么程度了。但如果只有一个线程单独处理这些操作,就非常好的能够管控。所以浏览器的模型就是单线程。
HTML5
提出Web Worker
标准,允许JavaScript
脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM
。所以,这个新标准并没有改变JavaScript
单线程的本质。
所以在早期,当使用大量同步的代码时,打开网页就会出现卡屏、卡页面的情况。因为在获取数据的时候,使用同步的代码,后面的数据还没到来之前,获取数据之后的代码都无法执行。只有等获取数据全部结束后,才会执行下面的代码。
所以后来,大家都知道了。开始使用异步。
同步队列 / 任务队列
既然是单线程,就意味着需要排队,即前面的任务结束,后面的任务才能执行。所以所有的任务被分成了两种,一种是同步任务,一种就是异步任务。同步任务指的就是在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行后一个任务。而异步任务指的是,不进入主线程(同步队列 stack
),而是进入任务队列(task queue
)的任务。只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
只要主线程空了,就会去读取 "任务队列" ,这就是
JavaScript
的运行机制。这个过程会不断重复。
重新理解这张图
例如我们有一段代码,这些代码是用来做一些操作。正常情况下,代码都是放置在栈(stack
)中的,正常执行的时候是一个个去执行的。但是有些时候,比如给页面元素绑定一个事件,发了一条 ajax
请求,或者还有一些异步处理。这个时候,就不能够放置在 stack
中了。不然就会处于长久的等待之中,其他的代码就无法按顺序即使的执行。
所以在浏览器里面,还有一个可以被称之为任务队列的地方。对于一些异步的任务,都是放到任务队列里面。举例来说,当用户给一个元素绑定事件 onClick
,绑定事件的操作在 stack
执行,但 onClick
回调本身是放到任务队列里面的。

重新理解 setTimeout
之前认识 setTimeout
时,就已经见过这段代码了,他的输出结果是先输出 2
,后才输出 1
。原理也是因为单线程机制。
setTimeout(function(){
console.log(1)
},0) console.log(2)
即 console.log(2)
被放入到 stack
中执行,setTimeout()
被放入到 callback queue
了。换句话说,必须要等所有 stack
中的同步的代码全都执行完后,才会去执行异步的事件。所以不管 setTimeout()
里面的时间是 0
还是 1000
都会被排到后面。
所以下面这个例子,1
永远不会被输出,且 2
被循环多次后,会被卡死。因为永远都在执行 console.log(2)
这个同步代码。而整个 stack
栈都被堵死了。 setTimeout()
根本没办法执行。
var isOk = true
setTimeout(function(){
console.log(1)
isOk = false
},1000) while(isOk){
console.log(2)
}
分析原生 Ajax
所以再去分析原生 Ajax
里面的代码,也能够更好的理解同步任务和异步任务。

这次,我想我真的理解了 JavaScript
的单线程机制。
博客园大佬比较多... 由于本人水平有限。如果这篇博文中一些地方有错误,或者各位大佬觉得我还是没有理解单线程机制和异步,请轻喷...
我想这次我真的理解了 JavaScript 的单线程机制的更多相关文章
- Javascript:再论Javascript的单线程机制 之 DOM渲染时机
Javascript:再论Javascript的单线程机制 之 DOM渲染时机 背景 Javascript是单线程事件驱动的,所有能看到的Javascript代码都是在一个线程执行,定时器回调和AJA ...
- Javascript引擎单线程机制及setTimeout执行原理说明
setTimeout用法在实际项目中还是会时常遇到.比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM,如果再这个函数堆栈中把页面背景先从白色设为红色,再设回白色,那么浏览器会认为DOM没有发生任何 ...
- JavaScript的异步机制
我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何 1 先看下两 ...
- 我理解的javascript单线程机制
废话不多说,我们先来看几个例子: 1. setTimeout( console.log(2); result: 2 1 2. console.log(100 setTimeout( cons ...
- Javascript是单线程的深入分析
本来想总结一下的,网上却发现有人已经解释的很清楚了,特转过来. 这也解释了为什么在用自动化测试工具来运行dumrendtree时设定的超时和测试case设定的超时的关联性. 面试的时候发现99%的童鞋 ...
- 简述JavaScript的运行机制
想要理解JavaScript的运行机制,需要分别深刻理解以下几个点: · JavaScript的单线程机制 · 任务队列(同步任务和异步任务) · 事件和回调函数 · 定时器 · Event Loop ...
- 您真的理解了SQLSERVER的日志链了吗?
您真的理解了SQLSERVER的日志链了吗? 先感谢宋沄剑给本人指点迷津,还有郭忠辉童鞋今天在QQ群里抛出的问题 这个问题跟宋沄剑讨论了三天,再次感谢宋沄剑 一直以来,SQLSERVER提供了一个非常 ...
- Javascript事件模型系列(四)我所理解的javascript自定义事件
被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...
- 理解的javascript自定义事件
理解的javascript自定义事件 被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情, ...
随机推荐
- 解决dpdk中出现IOMMU not found的问题
问题 在使用VFIO前,需要在BIOS打开VT-x和VT-d,想把一个PCIe网卡透传到虚拟机中,发现虚拟机启动失败,提示IOMMU没有找到. 输入以下命令确定vt-d开启 dmesg | grep ...
- webapi中的模型验证
mic: https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/model-valida ...
- 1<=portNo<=4竟然在keil4.71里面不报错
1.if( 1<=portNo<=4 ) { CardIn2_CS_L; //pull low CardIn1_CS_H; CardOut1_CS_H; CardOut2_CS_H ...
- zookeeper启动时报错:Error contacting service. It is probably not running问题
查看zookeeper.out发现启动日志报错未找到java路径. 启动日志位于zookeeper-4.0.10/bin目录下 修改/etc/profile中环境变量得以解决.
- uboot中ftd命令
可以从u-boot官网源码下载一个比较新的u-boot, 查看它的cmd/fdt.cftp://ftp.denx.de/pub/u-boot/ fdt命令使用示例nand read.jffs2 320 ...
- i2c子系统
linux内核的I2C驱动框架总览(1)I2C驱动框架的主要目标是:让驱动开发者可以在内核中方便的添加自己的I2C设备的驱动程序,从而可以更容易的在linux下驱动自己的I2C接口硬件(2)源码中I2 ...
- SVN搭建(linux 7)
第一步:通过yum命令安装svnserve,命令如下: >yum -y install subversion 此命令会全自动安装svn服务器相关服务和依赖,安装完成会自动停止命令运行 若需查看s ...
- VB
on error resume next: 从该语句开始,遇到错误时程序不会中止,也不会出现错误提示,将继续运行.作用范围直至程序结束或语句所在函数等结束 Public Property :可读也可写 ...
- C++程序设计入门(上) string类的基本用法
string类中的函数 1. 构造 2. 追加 3. 赋值 4. 位置与清除 5. 长度与容量 6. 比较 7. 子串 8. 搜索 9. 运算符 追加字符串 string s1("Welc ...
- swiper 仿淘宝详情页面 视频图片切换
1.好兄弟,看一下是否是你需要的 2.废话不多说 直接上代码,复制粘贴一下 自己引用一下swiper.js和css 然后就可以开始玩儿了 <!DOCTYPE html> <html& ...