Javascript实现异步编程的过程


Posted in Javascript onJune 18, 2018

相信不少人对Javascript单线程表示怀疑:为何单线程可以实现异步操作呢?其实Javascript确实是单线程的(我们不妨把这个线程称作主线程),但它实现异步操作的方式确实借助了浏览器的其他线程的帮助。那其他线程是怎么帮助Javascript主线程来实现异步的呢?答案就是任务队列(task queue)和事件循环(event loop)。

任务队列

首先,作为单线程语言,在Javascript中定义的任务都会在主线程中执行。但是并不是每个任务都会立刻执行,而这种不立刻执行的任务我们称作异步任务。相反,那些立刻执行的任务我们把它们称作同步任务。而这些异步任务都会交给浏览器的其他线程去执行,但是主线程需要了解这些异步任务执行的状态,才方便进行下一步操作。

打个比方,主线程准备做饭,所以下达一个异步任务去买菜,异步任务买完菜之后得告诉主线程:“我买完菜啦”,这个时候主线程才好开始做饭。

而我们知道因为Javascript是单线程,所以上述的“下一步操作”没法直接定义在主函数里(不然就被当做同步任务直接执行了),那这些应该定义在哪里呢?答案就是异步任务的回调函数中。在Javascript异步机制中,任务队列就是用来维护异步任务回调函数的队列。这样一个队列用来存放这些回调函数,它们会等到主线程执行完所有的同步函数之后按照先进先出的方式挨个执行。那么执行完任务队列之后呢?Javascript主线程就执行完毕了吗?当然不是,不然网页加载完毕之后,谁来处理后续与用户的交互事件(比如点击事件)呢?

事件循环

Javascript实现异步编程的过程

我们通过上图来更加形象的了解Javascript的异步机制。

执行同步任务 -> 检查任务队列中是否有任务 -> [有如果则执行] -> 检查任务队列中是否有任务 -> [有如果则执行] -> ......
可见主线程在执行完同步任务之后,会无限循环地去检查任务队列中是否有新的“任务”,如果有则执行。而这些任务包括我们在异步任务中定义的回调函数,也包括用户交互事件的回调函数。通过事件循环,Javascript不仅很好的处理了异步任务,也很好的完成了与用户交互事件的处理。因为在完成异步任务的回调函数之后,任务队列中的任务都是由事件所产生的,因此我们也把上述的循环过程叫做事件循环。

异步机制实践

console.log('定时器去买菜吧')
setTimeout(function(){
 console.log('菜买完了,主线程去做菜吧')
}, 0)
console.log('你先去买菜,我先看个世界杯')

在浏览器中执行上述代码,兴许能更好地理解Javascript的异步机制。

总结

总而言之,Javascript单线程的背后有浏览器的其他线程为其完成异步服务,这些异步任务为了和主线程通信,通过将回调函数推入到任务队列等待执行。主线程所做的就是执行完同步任务后,通过事件循环,不断地检查并执行任务队列中回调函数。

Javascript 相关文章推荐
经典海量jQuery插件 大家可以收藏一下
Feb 07 Javascript
js下将字符串当函数执行的方法
Jul 13 Javascript
javascript中为某个元素指定事件的三种方式
Aug 07 Javascript
深入理解javascript原型链和继承
Sep 23 Javascript
Javascript中数组sort和reverse用法分析
Dec 30 Javascript
对JavaScript客户端应用编程的一些建议
Jun 24 Javascript
去除html代码里面的script正则方法
May 19 Javascript
原生js仿jquery一些常用方法(必看篇)
Sep 20 Javascript
正则表达式,替换所有HTML标签的简单实例
Nov 28 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
Nov 05 Javascript
详解promise.then,process.nextTick, setTimeout 以及 setImmediate的执行顺序
Nov 21 Javascript
javascript单张多张图无缝滚动实例代码
May 10 Javascript
详解JS函数stack size计算方法
Jun 18 #Javascript
jQuery使用动画队列自定义动画操作示例
Jun 16 #jQuery
node.js自动上传ftp的脚本分享
Jun 16 #Javascript
Vue中props的使用详解
Jun 15 #Javascript
基于jQuery实现的设置文本区域的光标位置
Jun 15 #jQuery
深入浅析Vue全局组件与局部组件的区别
Jun 15 #Javascript
react-native android状态栏的实现
Jun 15 #Javascript
You might like
图解上海144收音机
2021/03/02 无线电
PHP简洁函数(PHP简单明了函数语法)
2012/06/10 PHP
Yii实现Command任务处理的方法详解
2016/07/14 PHP
PHP实现生成模糊图片的方法示例
2017/12/21 PHP
PHP微信网页授权的配置文件操作分析
2019/05/29 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
javascript &&和||运算法的另类使用技巧
2009/11/28 Javascript
JS 非图片动态loading效果实现代码
2010/04/09 Javascript
避免 showModalDialog 弹出新窗体的原因分析
2010/05/31 Javascript
jquery multiSelect 多选下拉框
2010/07/09 Javascript
基于jQuery制作迷你背词汇工具
2010/07/27 Javascript
一个通过script自定义属性传递配置参数的方法
2014/09/15 Javascript
简介JavaScript中的getUTCFullYear()方法的使用
2015/06/10 Javascript
浅谈javascript原型链与继承
2015/07/13 Javascript
javascript 判断两个日期之差的示例代码
2015/09/05 Javascript
vue双向绑定简要分析
2017/03/23 Javascript
javascript高仿热血传奇游戏实现代码
2018/02/22 Javascript
在create-react-app中使用css modules的示例代码
2018/07/31 Javascript
Vue前后端不同端口的实现方法
2018/09/19 Javascript
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
2018/11/14 Javascript
微信小程序实现天气预报功能(附源码)
2020/12/10 Javascript
[48:20]OpTic vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
深入理解Python中的 __new__ 和 __init__及区别介绍
2018/09/17 Python
对python自动生成接口测试的示例讲解
2018/11/30 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
2019/08/05 Python
python PIL/cv2/base64相互转换实例
2020/01/09 Python
python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
2020/04/07 Python
keras实现多GPU或指定GPU的使用介绍
2020/06/17 Python
Tensorflow使用Anaconda、pycharm安装记录
2020/07/29 Python
python字典与json转换的方法总结
2020/12/28 Python
全球领先的鞋类零售商:The Walking Company
2016/07/21 全球购物
Unix控制后台进程都有哪些进程
2016/09/22 面试题
高级护理实习生自荐信
2013/09/28 职场文书
党员年终民主评议的自我评价
2013/11/05 职场文书
消防先进事迹材料
2014/02/10 职场文书
交通事故被告代理词
2015/05/23 职场文书