JavaScript单线程语言与异步操作

JavaScript最初是设计为浏览器中的脚本语言,因此最简单的设计方式是在浏览器中有一个单独的线程进行执行JavaScript脚本程序,所以,javascript是一门单线程语言,尽管,在最新的HTML5中提出了Web-Worker,但javascript是单线程这一核心仍未改变。
JavaScript语言里面有很多异步操作(事件+回调函数),比如setTimeout()等,单线程语言是怎样实现异步操作的?

JavaScript中的任务可以分为两类:

同步任务和异步任务,异步任务就是注册一个回调函数,等待某一个事件发生后,调用回调函数;
JavaScript Runtime 运行时(主要是浏览器和node.js)开始执行一段JavaScript代码的时候,

  • 按照顺序一行一行的执行,同步任务,在主线程中执行,异步任务(事件+回调函数),进入Event Table并注册函数;
  • 当指定的事件完成是,Event Table会将注册的回调函数放入Event Queue;
  • 主线程中的任务执行完成后,会去Event Queue中读取对应的函数,进入主线程执行;
  • 上述过程会不断重复,也就是常说的Event Loop(事件循环);

事件循环就是JavaScript语言执行的基本机制;

setTimeout(fn,ms)
功能:多少ms毫秒时间后,负责将回调函数放到Event Queue中,具体什么时间执行,由事件循环机制决定;

setTimeout(()=>{
    console.log("1");
},3000);

console.log("2");

setTimeout(fn,0):表示直接把fn放到Event Queue中,等待下一次事件循环,可能立马就可以执行;

setInterval(fn,ms):循环的每过多少ms毫秒,将fn放到Event Queue中,等待下一次事件循环;

任务分类

对任务有更精细的定义:

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

事件循环的顺序,决定js代码的执行顺序。
进入整体代码(宏任务)后,开始第一次循环,遇到注册宏任务的代码就注册一个宏任务,同样遇到注册微任务的代码就注册一个微任务;
本轮事件循环结束后,不是直接开始下一个事件循环,而是执行本轮事件循环中注册的微任务,执行完注册的微任务后,再进入下一次事件循环;

JavaScript单线程语言与异步操作_第1张图片

上述代码:

第一次事件循环:

1-3行代码,等待3秒后,然后再去注册一个宏任务;

5行代码,顺序执行,输入2

7-9行代码,注册一个微任务1

11-16行代码:创建Promise对象,首先输出4,通过then注册一微任务2

18-25行代码:注册一个宏任务;

第一次事件循环结束,开始执行本次事件循环注册的微任务:

微任务1输出3

微任务2输出5

第二次事件循环:

1-3行定时未到,没有注册宏任务;

执行18-25注册的宏任务:

输出6,注册一个微任务3

事件循环结束,开始执行本轮事件注册的微任务;

微任务3:输出7

3秒定时到,事件循环中出现新的宏任务;

第三次事件循环:

输出1

全部执行结束;

输出顺序:2,4,3,5,6,7,1

node.js的结果:注意在其他JavaScript运行时中的执行顺序没有验证

JavaScript单线程语言与异步操作_第2张图片

 

你可能感兴趣的:(前端开发)