实例分析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 相关文章推荐
jquery实现不同大小浏览器使用不同的css样式表的方法
Apr 02 Javascript
jQuery 1.9移除了$.browser可以使用$.support来替代
Sep 03 Javascript
JQuery的Ajax中Post方法传递中文出现乱码的解决方法
Oct 21 Javascript
2014最热门的JavaScript代码高亮插件推荐
Nov 25 Javascript
javascript框架设计读书笔记之模块加载系统
Dec 02 Javascript
JavaScript 中 avalon绑定属性总结
Oct 19 Javascript
浅述节点的创建及常见功能的实现
Dec 15 Javascript
使用jQuery卸载全部事件的思路详解
Apr 03 jQuery
详谈表单格式化插件jquery.serializeJSON
Jun 23 jQuery
Node.js文件编码格式的转换的方法
Apr 27 Javascript
vue路由切换之淡入淡出的简单实现
Oct 31 Javascript
Vue OpenLayer测距功能的实现
Apr 20 Vue.js
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中实现汉字转区位码应用源码实例解析
2010/06/14 PHP
PHP语言中global和$GLOBALS[]的分析 之二
2012/02/02 PHP
Linux Apache PHP Oracle 安装配置(具体操作步骤)
2013/06/17 PHP
php异常处理使用示例
2014/02/25 PHP
laravel 出现command not found问题的解决方案
2019/10/23 PHP
js新闻滚动 js如何实现新闻滚动效果
2013/01/07 Javascript
javascript中处理时间戳为日期格式的方法
2014/01/02 Javascript
下拉框select的绑定示例
2014/09/04 Javascript
Easyui 之 Treegrid 笔记
2016/04/29 Javascript
Javascript之BOM(window对象)详解
2016/05/25 Javascript
关于js二维数组和多维数组的定义声明(详解)
2016/10/02 Javascript
浅谈React 属性和状态的一些总结
2016/11/21 Javascript
百度搜索框智能提示案例jsonp
2016/11/28 Javascript
JS实现间歇滚动的运动效果实例
2016/12/22 Javascript
Javascript 实现 Excel 导入生成图表功能
2018/10/22 Javascript
使用Vue.observable()进行状态管理的实例代码详解
2019/05/26 Javascript
Vue代码整洁之去重方法整理
2019/08/06 Javascript
vue-cli随机生成port源码的方法
2019/09/02 Javascript
Vue项目开发常见问题和解决方案总结
2020/09/11 Javascript
Python迭代用法实例教程
2014/09/08 Python
python简单文本处理的方法
2015/07/10 Python
python实现飞机大战
2018/09/11 Python
神经网络相关之基础概念的讲解
2018/12/29 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
Django获取该数据的上一条和下一条方法
2019/08/12 Python
用python3 urllib破解有道翻译反爬虫机制详解
2019/08/14 Python
django自带serializers序列化返回指定字段的方法
2019/08/21 Python
python中复数的共轭复数知识点总结
2020/12/06 Python
Html5+CSS3+EL表达式问题小结
2020/12/19 HTML / CSS
如何进行Linux分区优化
2013/02/12 面试题
学前班教师的自我鉴定
2013/12/05 职场文书
班干部竞选演讲稿
2014/04/24 职场文书
大学生英语演讲稿
2014/04/24 职场文书
宣传部部长竞选演讲稿
2014/04/26 职场文书
2014年班主任德育工作总结
2014/12/05 职场文书
合同补充协议书
2016/03/24 职场文书