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获取地址栏参数插件(模仿C#)
Oct 26 Javascript
javascript中的throttle和debounce浅析
Jun 06 Javascript
jQuery实现Email邮箱地址自动补全功能代码
Nov 03 Javascript
jquery实现右侧栏菜单选择操作
Mar 04 Javascript
js鼠标跟随运动效果
Mar 11 Javascript
详解VUE的状态控制与延时加载刷新
Mar 27 Javascript
vue2 中如何实现动态表单增删改查实例
Jun 09 Javascript
vue-cli项目中怎么使用mock数据
Sep 27 Javascript
web前端页面生成exe可执行文件的方法
Feb 08 Javascript
Vue.js 图标选择组件实践详解
Dec 03 Javascript
Vue 2.0 侦听器 watch属性代码详解
Jun 19 Javascript
详解VUE中的插值( Interpolation)语法
Oct 18 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
初识ThinkPHP控制器
2016/04/07 PHP
Symfony2针对输入时间进行查询的方法分析
2017/06/28 PHP
PHP判断json格式是否正确的实现代码
2017/09/20 PHP
Smarty缓存机制实例详解【三种缓存方式】
2019/07/20 PHP
javascript创建和存储cookie示例
2014/01/07 Javascript
JQuery与JS里submit()的区别示例介绍
2014/02/17 Javascript
javascript怎么禁用浏览器后退按钮
2014/03/27 Javascript
javascript实现简单的贪吃蛇游戏
2015/03/31 Javascript
jQuery实现的简单拖拽功能示例
2016/09/13 Javascript
sea.js常用的api简易文档
2016/11/15 Javascript
基于jQuery实现Tabs选项卡自定义插件
2016/11/21 Javascript
setTimeout学习小结
2017/02/08 Javascript
vue单页应用中如何使用jquery的方法示例
2017/07/27 jQuery
解决低版本的浏览器不支持es6的import问题
2018/03/09 Javascript
Angular4 反向代理Details实践
2018/05/30 Javascript
JS在if中的强制类型转换方式
2018/07/15 Javascript
解决vue2 在mounted函数无法获取prop中的变量问题
2018/11/15 Javascript
如何使用JavaScript实现栈与队列
2019/06/24 Javascript
基于jQuery实现可编辑的表格
2019/12/11 jQuery
Python中利用原始套接字进行网络编程的示例
2015/05/04 Python
Python找出文件中使用率最高的汉字实例详解
2015/06/03 Python
分享一下Python 开发者节省时间的10个方法
2015/10/02 Python
Python排序搜索基本算法之选择排序实例分析
2017/12/09 Python
Python 中如何实现参数化测试的方法示例
2019/12/10 Python
python自动从arxiv下载paper的示例代码
2020/12/05 Python
CSS3+HTML5+JS 实现一个块的收缩与展开动画效果
2020/11/17 HTML / CSS
天美时手表加拿大官网:Timex加拿大
2016/09/01 全球购物
size?荷兰官方网站:英国高级运动鞋精品店
2020/07/24 全球购物
为数据库创建索引都需要注意些什么
2012/07/17 面试题
编程输出如下图形
2013/11/24 面试题
大学生职业生涯规划范文
2013/12/31 职场文书
18岁生日感言
2014/01/12 职场文书
出纳年终工作总结2014
2014/12/05 职场文书
导游词之张家界
2019/10/31 职场文书
Redis Cluster 字段模糊匹配及删除
2021/05/27 Redis
使用Postman测试需要授权的接口问题
2022/06/21 Java/Android