事件循环和异步IO

一,事件循环

1. 什么是事件循环?

事实上我把事件循环理解成我们编写的JavaScript和浏览器或者Node之间的一个桥梁

  • 浏览器的事件循环是一个我们编写的JavaScript代码和浏览器API调用(setTimeout/AJAX/监听事件等)的一个桥梁, 桥梁之间他们通过回调函数进行沟通

  • Node的事件循环是一个我们编写的JavaScript代码和系统调用(file system、network等)之间的一个桥梁, 桥梁 之间他们通过回调函数进行沟通的

    image-20210924131257946

2. 进程和线程

  • 线程和进程是操作系统中的两个概念
    • 进程(process):计算机已经运行的程序;
    • 线程(thread):操作系统能够运行运算调度的最小单位
  • 多进程多线程开发
    • 这是因为CPU的运算速度非常快,它可以快速的在多个进程之间迅速的切换
    • 当我们的进程中的线程获取获取到时间片时,就可以快速执行我们编写的代码

3. 浏览器和JavaScript

  • 浏览器是一个进程吗,它里面只有一个线程吗?
    • 目前多数的浏览器其实都是多进程的,当我们打开一个tab页面时就会开启一个新的进程,这是为了防止一个 页面卡死而造成所有页面无法响应,整个浏览器需要强制退出
    • 每个进程中又有很多的线程,其中包括执行JavaScript代码的线程
  • 但是JavaScript的代码执行是在一个单独的线程中执行的
    • 这就意味着JavaScript的代码,在同一个时刻只能做一件事
    • 如果这件事是非常耗时的,就意味着当前的线程就会被阻塞

4. JavaScript执行过程

理解:类似完成任务,任务不断进入执行阶段(压栈),做完就出栈。(函数定义的时候没有执行,没有压栈)

image-20210924132629101

5. 浏览器的事件循环

  • 如果在执行JavaScript代码的过程中,有异步操作呢?
  • 中间我们插入了一个setTimeout的函数调用
  • 这个函数被放到入调用栈中,执行会立即结束,并不会阻塞后续代码的执行
  • 那么,传入的一个函数(比如我们称之为timer函数),会在什么时候被执行呢?
    • 事实上,setTimeout是调用了web api,在合适的时机,会将timer函数加入到一个事件队列中
    • 事件队列中的函数,会被放入到调用栈中,在调用栈中被执行

回调函数都会放到事件队列中。

image-20210924193900537

6. 宏任务和微任务

理解:微任务是高优先级任务,一出现就执行

  • main script中的代码优先执行(编写的顶层script代码)
  • 在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查看微任务队列中是否有任务需要执行
    • 在执行任何一个宏任务之前(不是队列,是一个宏任务),都会先查看微任务队列中是否有任务需要执行
    • 如果不为空,那么久优先执行微任务队列中的任务(回调)

7. 面试题分析,asyc,await

二,异步IO