实例分析javascript中的异步


Posted in Javascript onJune 02, 2020

js 异步解析

一 、js单线程分析

     我们都知道js的一大特点是单线程,也就是同一时间点,只能处理一件事,一句js代码。那为什么js要设计成单线程而不是多线程呢?这主要和js的用途有关,js作为浏览器端的脚本语言,主要的用途为用户与服务端的交互与操作dom。而操作dom就注定了js只能是单线程语言。假如js才取多线程将会出现,多个线程同时对一个dom进行操作的情况,浏览器将无法判断如何渲染。不仅js是单线程,浏览器渲染dom也是单线程的,js的执行和浏览器渲染dom共用的一个线程,这就导致了在html代码中书写js代码会造成浏览器端渲染的阻塞。例如:在html某个位置,写一个段带有alert(‘稍等'),alert 之前html已经被渲染出来,而alert之后的html被这段js阻塞了。为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完 全受主线程控制,且不可进行DOM操作。所以,这个新标准并没有改变JavaScript单线程的本质。

     所谓的js单线程,是指在浏览器中JS引擎负责解释和执行JavaScript代码的线程只有一个。不妨叫它主线程。但是实际上浏览器处理js还存在其他的线程。例如:处理AJAX请求的线程、处理DOM事件的线程、定时器线程、读写文件的线程(例如在Node.js中)等等。这些线程可能存在于JS引擎之内,也可能存在于JS引擎之外,在此我们不做区分。不妨叫它们工作线程

     总结一下:js之所以才取单线程模式是为了避免DOM渲染冲突。而浏览器中执行js线程是单线程我们称它为主线程,同时还存在其它处理js的线程,我们称它为工作线程。js是单线程,但浏览器是多线程的。

二 、同步与异步

     单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。这就是同步代码阻塞。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

     简单的说,同步就是会阻塞代码的执行,而异步不会。同样拿alert('稍等') 来举例,在一段js代码中加入一段alert,如果没有点击确认,此时代码的执行就被阻塞了,大多数js代码都是同步执行的。异步则相反。那为什么js中要引入异步的概念呢,很简单,由于js的单线程,当遇到耗时的操作时如果采用同步的执行,那么我们就不可能看到如今这么流畅的web应用了。再举个简单的例子:在一条单行道上行驶着很多汽车,假如其中某一辆车出现机械故障,将会导致后面的车也无法通过,此时应该将故障的车拉入旁边的应急车道进行修复,待它修好之后再重新驶入主干道中,不会影响主干道其它行驶的汽车。所以,异步是js单线程下解决耗时问题的一种“无可奈何”的解决方案。也是一种近乎完美的解决方案。

三、js异步与事件轮询

     事件轮询(event loop)是js异步的实现方式。简而言之,在js单线程中分为两种任务,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有当主进程中所有同步任务执行完毕,且”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。事件轮询就是将主线程中的异步任务挂载到任务队列中,再待到合的时机,将任务队列中的异步函数拉到主进程来执行的这么一个流程。

js中异步操作主要有:

     1、定时任务(setTimeout、setInterval)

     2、网路请求(ajax、动态<img>加载)

     3、事件绑定(click,focus,change等)

 js异步具体执行流程分析

实例分析javascript中的异步

     大家看一下左边代码,两个console.log操作,两个setTitmeout 操作。按照我们对异步的理解,在主线程中 console.log 为同步任务从上到下依次执行,所以在最先打印的是3,当执行到第一setTimeout时,浏览器js引擎会自动将setTimeout放入工作线程中。ps:在工作线程中,待0.1s后将setTimeout 的回调函数放入异步队列中;主进程中下一个setTimeout ,但是它的延迟时间为0,这并不意味着它能同步执行,它依旧经历如上两个过程,从工作进程中,0s后放入任务队列。接下来是执行console.log(3);当主进程中任务已经执行完毕。任务队列中有一个监视器,随时监视着主进程和任务队列中的异步函数情况,当主进程执行完毕,就判断任务队列中是否有需要执行的函数,如果有就按照队列现后顺序依次放入主进程中,以此往复。

     所以上面代码,依次打印为:3,3,2,1。也就是先将非异步执行完,再回过头来执行异步函数,异步函数执行顺序为队列规则,先进先出,也就是先进入队列的异步函数将优先执行。

     思考:如果一段代码中现后存在一个ajax 和一个1s的定时函数,那么他们谁先执行呢? 答案是:不确定。因为不确定ajax请求完毕进入队列的时间。小伙伴们可别被面试管套路了哦。哈哈。

四、前端异步的写法

     1、回调函数,也就是在setTimeout或者ajax中添加回调函数,待到指定时间后或者请求到数据后再执行回调。

     2、ES6标准:Promise,ES7:async await   这两种都只是js事件轮询实现异步的一种优雅的 方式,将异步变为同步的写法,但都并未改变js异步本质。

以上就是实例分析javascript中的异步的详细内容,更多关于javascript 异步的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript实现的像java、c#之类的sleep暂停的函数代码
Mar 04 Javascript
jquery动态添加option示例
Dec 30 Javascript
jQuery延迟加载图片插件Lazy Load使用指南
Mar 25 Javascript
使用iojs的jsdom库实现同步系统时间
Apr 20 Javascript
跟我学习javascript的异步脚本加载
Nov 20 Javascript
javascript中的 object 和 function小结
Aug 14 Javascript
详解AngularJS跨页面传值(ui-router)
Aug 23 Javascript
css和js实现弹出登录居中界面完整代码
Nov 26 Javascript
JS实现移动端触屏拖拽功能
Jul 31 Javascript
微信小程序实现弹出层效果
May 26 Javascript
微信小程序获取用户绑定手机号方法示例
Jul 21 Javascript
Vue自定义组件双向绑定实现原理及方法详解
Sep 03 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
Jun 02 #Javascript
js简单实现自动生成表格功能示例
Jun 02 #Javascript
JS中准确判断变量类型的方法
Jun 01 #Javascript
Vuex中的Mutations的具体使用方法
Jun 01 #Javascript
vue使用自定义事件的表单输入组件用法详解【日期组件与货币组件】
Jun 01 #Javascript
Bootstrap table 服务器端分页功能实现方法示例
Jun 01 #Javascript
easyUI 实现的后台分页与前台显示功能示例
Jun 01 #Javascript
You might like
PHP中Array相关函数简介
2016/07/03 PHP
PHP会话控制实例分析
2016/12/24 PHP
ThinkPHP模板标签eq if 中区分0,null,false的方法
2017/03/24 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
本地对象Array的原型扩展实现代码
2010/12/04 Javascript
event.X和event.clientX的区别分析
2011/10/06 Javascript
8款非常棒的响应式jQuery 幻灯片插件推荐
2012/02/02 Javascript
JQuery插件fancybox无法在弹出层使用左右键的解决办法
2013/12/25 Javascript
javascript实现随时变化着的背景颜色
2015/04/02 Javascript
jQuery中inArray方法注意事项分析
2016/01/25 Javascript
JSP防止网页刷新重复提交数据的几种方法
2016/11/19 Javascript
AngularJS实现DOM元素的显示与隐藏功能
2016/11/22 Javascript
JavaScript 栈的详解及实例代码
2017/01/22 Javascript
原生js实现日期计算器功能
2017/02/17 Javascript
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
2017/08/30 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
2019/01/24 jQuery
Vue数据双向绑定原理实例解析
2020/05/15 Javascript
python多线程编程方式分析示例详解
2013/12/06 Python
python3+PyQt5实现支持多线程的页面索引器应用程序
2018/04/20 Python
Python实现的当前时间多加一天、一小时、一分钟操作示例
2018/05/21 Python
PyQt5实现QLineEdit添加clicked信号的方法
2019/06/25 Python
Python如何使用OS模块调用cmd
2020/02/27 Python
Python模块相关知识点小结
2020/03/09 Python
Python3爬虫ChromeDriver的安装实例
2021/02/06 Python
h5页面背景图很长要有滚动条滑动效果的实现
2021/01/27 HTML / CSS
计算机应用专业应届毕业生中文求职信范文
2013/11/29 职场文书
车辆安全检查制度
2014/01/12 职场文书
会计大学生职业生涯规划书范文
2014/01/13 职场文书
出纳会计岗位职责
2014/03/12 职场文书
2014年祖国生日寄语
2014/09/19 职场文书
党员对十八届四中全会的期盼思想汇报范文
2014/10/17 职场文书
2016优秀班主任个人先进事迹材料
2016/02/26 职场文书
幽默口才训练经典句子(48句)
2019/08/19 职场文书
2019员工保密协议书(3篇)
2019/09/23 职场文书
利用python调用摄像头的实例分析
2021/06/07 Python