实例分析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 相关文章推荐
CLASS_CONFUSION JS混淆 全源码
Dec 12 Javascript
event对象的方法 兼容多浏览器
Jun 27 Javascript
解决js函数闭包内存泄露问题的办法
Jan 25 Javascript
动态的9*9乘法表效果的实现代码
May 16 Javascript
jquery自动补齐功能插件flexselect用法示例
Aug 06 Javascript
vue 刷新之后 嵌套路由不变 重新渲染页面的方法
Sep 13 Javascript
详解node字体压缩插件font-spider的用法
Sep 28 Javascript
Vue数据双向绑定的深入探究
Nov 27 Javascript
微信小程序之swiper滑动面板用法示例
Dec 04 Javascript
原生JS实现的跳一跳小游戏完整实例
Jan 27 Javascript
小程序显示弹窗时禁止下层的内容滚动实现方法
Mar 20 Javascript
AJAX引擎原理以及XmlHttpRequest对象的axios、fetch区别详解
Apr 09 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使用GETDATE获取当前日期时间作为一个关联数组的方法
2015/03/19 PHP
PHP解压tar.gz格式文件的方法
2016/02/14 PHP
PHP获取网站中各文章的第一张图片的代码示例
2016/05/20 PHP
PHP7基于curl实现的上传图片功能
2018/05/11 PHP
PHP操作redis实现的分页列表,新增,删除功能封装类与用法示例
2018/08/04 PHP
Laravel中9个不经常用的小技巧汇总
2019/04/16 PHP
RGB颜色值转HTML十六进制(HEX)代码的JS函数
2009/04/25 Javascript
javascript 定义初始化数组函数
2009/09/07 Javascript
jQuery去掉字符串起始和结尾的空格(多种方法实现)
2013/04/01 Javascript
如何从jQuery的ajax请求中删除X-Requested-With
2013/12/11 Javascript
javascript自动给文本url地址增加链接的方法分享
2014/01/20 Javascript
DOM基础教程之使用DOM控制表格
2015/01/20 Javascript
iPhone手机上搭建nodejs服务器步骤方法
2015/07/06 NodeJs
jQuery实现的Tab滑动选项卡及图片切换(多种效果)小结
2015/09/14 Javascript
深入浅析javascript立即执行函数
2015/10/23 Javascript
Treegrid的动态加载实例代码
2016/04/29 Javascript
页面get请求 中文参数方法乱码问题的快速解决方法
2016/05/31 Javascript
使用BootStrap实现标签切换原理解析
2017/03/14 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
关于javascript获取内联样式与嵌入式样式的实例
2017/06/01 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
2017/09/11 Javascript
vue移动端路由切换实例分析
2018/05/14 Javascript
js设置鼠标悬停改变背景色实现详解
2019/06/26 Javascript
jQuery实现获取多选框的值示例
2020/02/07 jQuery
[45:10]NB vs Liquid Supermajor小组赛 A组胜者组决赛 BO3 第二场 6.2
2018/06/04 DOTA
[01:33:07]VGJ.T vs Newbee Supermajor 败者组 BO3 第一场 6.6
2018/06/07 DOTA
Python sys.argv用法实例
2015/05/28 Python
解决pycharm不能自动补全第三方库的函数和属性问题
2020/03/12 Python
10个示例带你掌握python中的元组
2020/11/23 Python
html5 worker 实例(二) 图片变换效果
2013/06/24 HTML / CSS
AVIS安飞士奥地利租车官网:提供奥地利、欧洲和全世界汽车租赁
2016/11/29 全球购物
美国花园雕像和家居装饰网上商店:Design Toscano
2019/03/09 全球购物
平面设计师工作职责范文
2013/12/03 职场文书
2014年公司植树节活动方案
2014/03/04 职场文书
学校重阳节活动总结
2015/03/24 职场文书
postgresql无序uuid性能测试及对数据库的影响
2021/06/11 PostgreSQL