js的执行机制

js是一门单线程语言

js的执行机制就是事件循环(Event Loop)

1.JavaScript是单线程

JavaScript是一门单线程语言,也就是说同一时间只能做一件事。

2.为什么JavaScript是单线程

作为浏览器脚本语言,JavaScript主要用途是与用户互动以及操作DOM,所以它只能是单线程,否则会带来很严重的同步问题,如果JavaScript有两个线程,一个线程在DOM节点上添加内容,另一个线程删除这个节点,要以哪个线程为指令呢?

3.为什么js需要异步任务?

js是单线程,那么js任务也需要一个一个执行,如果一个任务消耗时间很长,那么后面的任务也需要等待。如果js不存在异步,只能自上而下执行,如果上一行解析时间很长,下面的代码就会堵塞,堵塞就意味着"卡死",用户体验会极差。

4.js存在同步任务和异步任务

同步任务:在主线程上排队执行任务,只有前一个任务执行完毕,才能执行后一个任务

异步任务:不进入主线程,而是进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

除了广义的同步任务和异步任务,对任务更精细的定义:

macro-task(宏任务):包括整体代码script,setTimeout,setInterval

micro-task(微任务):Promise,process.nextTick

宏任务中有微任务,一定要将宏任务中的微任务执行完毕,再去执行下一个宏任务。

5.js事件循环是怎样运作的

js的执行机制_第1张图片

  1. 同步任务和异步任务分别进入不同的“场所”,同步任务进入主线程,异步任务进入Event Table (事件表)并注册函数
  2. 指定的事件完成后,Event Table (事件表)会将这个函数移入到Event Queue (事件队列)
  3. 当主线程的任务完成后,会检查Event Queue (事件队列),如果有任务就全部执行,如果没有就进入下一个宏任务
  4. 这个过程会不断的重复,这就叫事件循环

6.例题

eg1:

console.log(1);

setTimeout(function(){
    console.log(2);
    process.nextTick(function(){
        console.log(3);
    })
    new Promise(function(resolve){
        console.log(4);
        resolve();
    }).then(function(){
        console.log(5);
    })
})

process.nextTick(function(){
    console.log(6);
})

new Promise(function(resolve){
    console.log(7);
    resolve();
}).then(function(){
    console.log(8);
})

setTimeout(function(){
    console.log(9);
    process.nextTick(function(){
        console.log(10);
    })
    new Promise(function(){
        console.log(11);
        resolve();
    }).then(function(){
        console.log(12)
    })
})

第一轮事件循环

一、整体script宏任务,从上到下执行。

  1. 遇到console.log(),输出1
  2. setTimeout1添加到宏任务队列中,待执行
  3. process.nextTick1添加到微任务队列中,待执行
  4. 遇到new Promise直接执行输出7,then加入到微任务队列,记微then1
  5. setTimeout2添加到宏任务队列中,待执行

js的执行机制_第2张图片

二、执行微任务队列

  1. 执行prcess.nextTick1这个微任务,输出6
  2. 执行then1这个微任务,输出8
  3. 微任务队列清空,第一轮循环结束

js的执行机制_第3张图片

第二轮事件循环

三、执行宏任务队列

  1. 执行setTimeout1这个宏任务
  2. 遇到console.log,输出2
  3. process.nextTick2添加到微任务队列
  4. 执行new Promise,输出4
  5. then添加到微任务队列,记为then2

js的执行机制_第4张图片

四、执行微任务队列

  1. 执行process.nextTick2这个微任务,输出3
  2. 执行then2这个微任务,输出5
  3. 微任务队列清空,第二轮循环结束

js的执行机制_第5张图片

第三轮事件循环

五、执行宏任务队列

  1. 执行setTimeout2这个宏任务
  2. 遇到console.log,输出9
  3. process.nextTick3添加到微任务队列
  4. 执行new Promise,输出11
  5. then添加到微任务队列,记为then3

js的执行机制_第6张图片

六、执行微任务队列

  1. 执行process.nextTick3,输出10
  2. 执行then3这个微任务,输出12
  3. 微任务队列清空,第三轮循环结束

eg2:

console.log('1');

setTimeout(() => {
    console.log('2');
},100)

setTimeout(() => {
    console.log('3')
    new Promise(resolve => {
        console.log('4');
        resolve();
    }).then(() => {
        console.log('5')
    })
},100)

Promise.resolve().then(() => {
    console.log('6');
})

new Promise(resolve => {
    console.log('7');
    resolve();
    setTimeout(() => {
        console.log('8')
    },100)
}).then(() => {
    console.log('9');
    setTimeout(() => {
        console.log('10')
    },100)
})

console.log('11');
//1 7 11 6 9 2 3 4 5 8 10

一、首先,整体script宏任务

  1. 遇到console.log , 输出1
  2. setTimeout1添加到宏任务队列中,待执行
  3. setTimeout2添加到宏任务队列中,待执行
  4. then1添加到微任务队列中,待执行
  5. 执行new Promise输出7,将setTimeout3添加到宏任务队列中,将then2添加到微任务对列中
  6. 遇到console.log,输出11

二、执行微任务队列

  1. 执行then1,输出6
  2. 执行then2,输出9,将setTimeout4添加到宏任务队列

三、执行宏任务队列

  1. 执行setTimeout1这个宏任务,输出2
  2. 执行setTimeout2这个宏任务,输出3,执行new Promise输出4,将then3添加到微任务对列中

四、执行微任务队列

  1. 执行then3,输出5

五、执行宏任务队列

  1. 执行setTimeout3这个宏任务,输出8
  2. 执行setTimeout4这个宏任务,输出10

总之,执行的顺序就是,执行宏任务,再执行宏任务里面的微任务,如果执行微任务的过程中,产生了新的微任务,则继续执行微任务,等到微任务执行结束,再回到宏任务中进行下一轮循环

你可能感兴趣的:(周记,其他)