博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
你必须要了解的异步
阅读量:6799 次
发布时间:2019-06-26

本文共 2198 字,大约阅读时间需要 7 分钟。

前言

总所周知,javascript是单线程运行的,并没有多线程运行这么一说,那为什么会有异步进行的说法呢。 这里就要纠正一个概念,异步和多线程并行是不同的,异步只是在现在和将来之间进行切换,并不是代表着多线程同时运行。

正文

什么是js异步

在javascript中,异步的概念只是说将现在要发生的事情,放到将来去运行,做为单线程程序,在同一时间只会运行一个主程序代码,不会存在多个经常在同时运作,就不会有多进程的编写,那么,这么说的话,js的异步究竟是如果进行的呢,接下来慢慢分析

回调函数

回调在一定程度上能够代表着异步进程,因为大多数内容都是可以通过回调进行异步,例如ajax,使用ajax之后,我们会提供一个回调函数,然后在一定时间后浏览器会响应我们的回调函数,那么,具体操作是什么呢?

当然这里可能不是浏览器,也可能是其他的宿主对象,我就暂时以浏览器的内容做一个简单的介绍(后续文章会对回调做一个完整的介绍)

  1. 首先我们发送了ajax请求,然后通知了我们的浏览器,我需要暂停这个服务了,因为这个时候还在等待期间,如果,ajax不暂停,而在一直等待的话,那么我们整个服务就卡在那边需要等待ajax请求结束才能在继续使用,所以,在这个时候,它会告诉浏览器,你等这个http请求返回了结果,你就去调用我给你看的这个函数
  2. 浏览器收到了这个请求,然后就不去等待ajax的返回,接下去执行另一段代码
  3. 等http返回了内容,浏览器终于知道了,你服务好了,那我要去调用这个方法了,但是我们也说过,js是单线程的,不可能会因为这个事件好了,那我就停下来当前的事情,先去处理这个返回,所以这里就涉及到了我们的js事件循环

事件循环(event loop)

event loop其实分为两种,一种是在浏览器端的事件循环,一种是在服务器端的(nodejs),这里我们只介绍浏览器层次的内容,关于nodejs的event loop在后续的学习中,会陆续介绍。

在事件循环中,js在运行的时候,会生成一个任务队列,循环去执行,任务分为两种任务进度,宏任务跟微任务

宏任务(task)

js运行的主任务,每次执行完当前的task内全部任务,就会去重新渲染一边页面内容, task内容包括:

  1. 主js流程代码块
  2. dom的click等响应事件
  3. settimeout产生的异步事件
  4. ...

微任务 (Microtasks)

microtasks 运行在task之后,每次当前的task内部任务完成之后,会立即去执行microtasks内部的任务,然后再进行新的一轮task的任务队列,microtasks包括:

  1. promise回调
  2. mutation observe回调
  3. ...

简单的案例

function a(){    console.log(1);    Promise.resolve().then(function(res){        console.log(2);    })    setTimeout(function(){        console.log(4);        Promise.resolve().then(function(res){            console.log(5);        })        console.log(6);    })    console.log(3);}复制代码

那么这个案例会怎么输出呢,答案是1,3,2,4,6,5。

不知道大家猜到了没有,按照先前的叙述,浏览器会先运行a方法里面的主流程,即打印出1,3,然后将第一个promise放进下一个微任务,将settimeout放入下一个宏任务,当第一个宏任务结束的时候,就会执行了下一个微任务就是第一个promise,等第一个promise运行结束之后又会重新开始后续的宏任务队列,由于第二个promise是在settimeout中执行的,所以只有当第二次宏任务执行的时候,才会将第二个promise放入微任务队列,所以我们能够很轻易的得出答案就是132465.

这就是js在执行异步操作的时候会执行的整个过程,接下来我们来了解了解,并行是一个什么样的过程

并行

其实在我看来,并行是属于异步的一种分支,因为并行本质上是多条内容在同步执行,但是,既然鉴于我们之前了解的js是一个单线程运行程序,那为什么会有并行这么一说呢。

什么是并行

其实js中的并行,更详细点讲,就是多个http请求同时发出,浏览器等待回应。因为js本身在浏览器中是不支持多线程运行的,但是并不阻挡js监听http返回的内容。所以当我们加载页面的时候,多个请求同时发送,就构成了广义上的并行

并行会有什么问题

  • 无法确定回调顺序
  • 对相同数据进行处理会产生覆盖或修改操作

如何解决

  1. 对于必须要的请求,如果对相同数据做操作,放进回调后再去调用
  2. 为了避免回调地狱,可以用async 跟 await进行回调写法
  3. 并行加载初始化数据,不要让返回的内容,输入在同一个变量中
  4. 对多个请求,只获取其中一个数据的,可以设置门闩,拿第一个或者最后一个,或者确定的一个数据源

总结

对于js异步,其实是一个任务队列的不断循环操作,不管是回调还是监听,实际上都是放在任务队列中,然后通过事件循环不断的去调用,触发,希望对你们有所用

转载地址:http://ojfwl.baihongyu.com/

你可能感兴趣的文章
poj 2528 Mayor's posters(线段树+离散化)
查看>>
动画绘制水波纹
查看>>
安装xenomai的记实
查看>>
梦幻星空动画
查看>>
用Easing函数实现碰撞效果
查看>>
Python简介
查看>>
泛函编程(13)-无穷数据流-Infinite Stream
查看>>
XML与HTML
查看>>
[Java 泥水匠] Java Components 之二:算法篇之项目实践中的位运算符(有你不懂的哦)...
查看>>
Java SecurityManager
查看>>
[LeetCode]*84.Largest Rectangle in Histogram
查看>>
[华为机试练习题]8.汽水瓶
查看>>
taskset - retrieve or set a process's CPU affinity (affect SYSTEMTAP TIME)
查看>>
SpringBoot2 | SpringBoot启动流程源码分析(二)
查看>>
MyBatis 原理浅析——基本原理
查看>>
第七章:SpringCloud Feign对hystrix的支持
查看>>
从零开始学习hadoop之发行版选择
查看>>
Redis radix tree源码解析
查看>>
数组和链表
查看>>
撩课-Java面试宝典-第三篇
查看>>