秒懂JS中的同步/异步编程是什么

1. 进程(process)/线程(thread)

进程process: 电脑端安装不少的应用软件,每当运行一个应用程序,至关于开辟一个进程(而对于浏览器来讲,每新建一个页卡访问一个页面,都是新开辟一个进程)web

  • 任务管理器能够查看进程

线程thread: 每个进程中可能还会同时作不少事情,若是程序中须要同时处理不少事情,则须要开辟多个线程(一个线程同时只能作一个事情)编程

=> 一个进程中,会包含0~多个线程promise

理解:浏览器

  • 每个饭店是一个进程
  • 饭店里面每个点餐的服务员就是一个线程

2. JS是单线程的线程

浏览器是‘多线程’的,可是JS渲染或者页面渲染是‘单线程’的多线程

2.1 浏览器中线程的分类

  • GUI渲染线程(渲染和绘制页面)
  • JS引擎线程(运行和渲染JS代码)
  • 事件管控和触发线程
  • 定时器管控和触发线程
  • 异步HTTP请求线程
  • ...

2.2 JS代码的渲染是单线程的

浏览器是多线程的(打开一个页面之后,浏览器至少要分配好几个线程同时去处理事情),可是浏览器只会分配出一个线程去渲染代码(GUI渲染线程),因此说JS是单线程的:‘在JS代码执行过程当中,一次只能处理一个事情’异步

3. 同步与异步

  • 同步编程【单线程】:任务是一次执行,上面的任务没有执行完成,下面的任务是不能去操做的
  • 异步编程【多线程】:同时能够处理不少事情,可是JS中的异步编程是利用浏览器的相关机制构造出来的异步效果

通俗的理解:好比咱们在食堂打饭这个场景: 咱们在排队打饭,可是当排到B打饭的时候,他的王者荣耀游戏尚未打完(吃饭不积极,思想...😅)async

  • 此时同步编程思想处理的方式就是:咱们你们都等B打完游戏,只要B不打饭,后面的也不能打饭(B不会就是食堂老板的儿子吧,这么多人等他打游戏🤔)
  • 可是异步编程思想处理方式是这样的:无论你的后台有多大,腾不出手,就去旁边的任务队列等着去,等咱们你们都打完饭,你的游戏也打完了,再来打饭(这你还怎么猖狂😂)
同步编程
同步编程
异步编程
异步编程

3.1 常见的异步代码

  • 定时器:设置定时器是同步(当即设置),异步指的是间隔多久后执行指定的函数
  • 事件绑定(监听)
  • AJAX的异步请求
  • promise/async/await

4 定时器

  • setTimeout
  • setInterval

4.1 定时器的返回值

返回值:是一个数字,表明当前是第几个定时器编辑器

  • 咱们后期能够基于clearTimeout / clearInterval 清除定时器
  • 手动把timer赋值为null,后期基于它的值验证是否存在定时器

4.2 浏览器的最小反应时间

  • 定时器是异步的:遇到定时器先不执行,先去执行其余事情,等到全部事情作完再看那个定时器到达时间而后能够立马执行;
  • 定时器的等待时间即便设置为零,也不是当即执行,浏览器有一个最小的等待时间(谷歌5~6MS IE浏览器10~13MS
  • 最小反应时间:在滚动相同的距离下,事件被触发多少次,取决于滚动所用的时间(速度)来决定的,浏览器有最小的反应时间,假设是5MS,总体运动时间100MS,这段时间内,浏览器可以识别出来的次数是100/5 = 20次。同理,若是咱们运动1000MS,那么识别触发的次数就是1000/5=200次

4.3 从定时器的执行过程理解它的异步的

  • 把代码拿到栈中执行,当遇到异步代码定时器的时候,会当即把定时器拿到任务队列中去等待必定时间
  • 当把主线程的全部代码执行完毕以后,去任务队列中查看哪一个定时器到达时间,把到达时间的定时器拿到栈中执行(这种操做是异步)

=> 遇到定时器不是不处理,而是把它放在任务队列,等到主线程空闲下来,再去任务队列查看,这种操做是异步。中途定时器到达时间了,可是主线程并无到达时间,此时也不会当即执行定时器,必须等到主线程空闲下来。异步编程

4.4 下面是关于定时器的对异步代码的理解,配有图片和注释的说明👇

4.4.1 题目一

let n = 0;
setTimeout(() => {  n++;  console.log(n); //=> 3 (2) }, 1000); //一秒钟以后执行 n += 2; console.log(n); //=> 2 (1) 复制代码
题目一
题目一

4.4.2 题目二

let n = 0;
setTimeout(() => {  n++;  console.log(n); //=> 3 (2) },0); //写零也不是当即执行,而是有一个最小的等待时间:10ms左右 n += 2; console.log(n); //=> 2 (1) 复制代码

4.4.3 题目三

let n = 10;
setTimeout(() => {  n++;  console.log(n); //=>11(3) }, 0); console.log(n); //=>10(1) for(let i = 0;i < 99999999; i++){} console.log(n); //=>10(2) 复制代码
题目三
题目三

4.4.4 题目四

time / timeEnd:获取他们中间代码执行所须要的时间(这个时间须要受到电脑配置、和当前电脑运行的环境等多方面因素影响),时间只做为参考函数

setTimeout(() => {
 console.log(1); }, 20); console.log(2); setTimeout(() => {  console.log(3); }, 10); console.log(4); console.time('AA'); for (let i = 0; i < 90000000; i++) {  // do soming } console.timeEnd('AA'); //=>AA: 79ms 左右 console.log(5); setTimeout(() => {  console.log(6); }, 8); console.log(7); setTimeout(() => {  console.log(8); }, 15); console.log(9); 复制代码
题目四
题目四

4.4.5 题目五

console.log(1); //=>1(1)
setTimeout(function () {  console.log(2); }, 20); console.log(3); //=>3(2) for (let i = 0; i > -1; i++) {} //=>死循环,GUI线程啥都作不了,一直在这加载(其它什么事情都干不了) console.log(4); setTimeout(function () {  console.log(5); }, 10); console.log(6); 复制代码

5. 事件循环 Event Loop

定义:JS是单线程的,由于浏览器只分配一个线程自上而下加载代码。因此JS中大部分任务都是同步任务。可是必定也有异步任务,定时器、事件绑定等这些都属于异步任务。

而浏览器处理JS中的异步任务是:在JS代码自上而下执行的时候,代码进栈执行,执行完出栈,在这反反复复进行的过程当中。当遇到定时器等异步任务的时候,会把当前任务放在等待任务队列(Event Queue)中存起来,而且存起来以后不会影响下面代码的执行,主线程会继续执行。当 把下面的同步任务执行完成以后,主线程空闲下来了会去等待队列找哪个任务到达指定的时间点,就拿到主线程中去执行。执行完以后再去等待队列中查看...

相关文章
相关标签/搜索