2

【视频资源已上架哔哩哔哩,关注up主波罗丁的菠萝】

hello大家好,本次分享一下关于JavaScript执行机制的知识点。那么废话不多说,直接上结论,首先我们知道JavaScript是一门单线程语言,决定JavaScript执行顺序的并不是代码顺序,而是event loop顺序。

我们先来讲解一下什么是同步任务,什么是异步任务。同步任务就是按照代码写的顺序一步一步执行下去,而异步代码呢,会先将要执行的代码放入异步队列里,然后执行同步代码,等同步代码全部执行完毕之后,再去异步队列里去查看是否有待执行的代码,如果有的话,就会执行。

用setTimeout演示一下

setTimeout(()=>{
    console.log('timeout');
},0);

console.log('11111');

我们先不看执行结果是什么,先把这段代码的event loop顺序安排一下

// 首先进入整体代码
// 接着遇到了setTimout,执行它,把它对应的方法放到异步队列里去,等0ms之后再来执行它
// 接着走,遇到了console.log('11111');执行它,输出1111
// ok同步的执行完了,我去异步队列瞅瞅还有啥

// 异步队列
// 发现了console.log('timeout');,ok执行它就完了
console.log('timeout');

注意一下setTimeout第二个参数,等0ms之后再执行它,0ms之后需要看同步任务是否已经执行完毕,如果同步任务还在执行,那么只好继续等下去直到同步任务执行完毕

比如

// 1000ms后执行
setTimeout(()=>{
    console.log('timeout');
},1000);

alert('同步阻塞');

拿着去浏览器里执行一下,会发现只要我不点按钮一直让同步任务阻塞住它就不输出timeout

接下来我们再说一下Promise

let p = new Promise((resolve,reject)=>{
  console.log('promise');
  resolve();
});
p.then(()=>{
  console.log('resolve');
});
console.log('同步');

我们先不看执行结果是什么,先把这段代码的event loop顺序安排一下

// 首先进入整体代码
// 接着遇到了new Promise,执行它,输出console.log('promise')
// 接着走,遇到了promise的then;执行它,把它对应的代码放到异步队列里
// 接着走,遇到了console.log('同步');执行它,输出同步
// ok同步的执行完了,我去异步队列瞅瞅还有啥

// 异步队列
// 发现了console.log('resolve');,ok执行它就完了,输出resolve
console.log('resolve');

那么Promise和setTimeout有什么不同呢,看着都一样啊,咱们也不磨叽直接上结论,在JavaScript除了同步任务和异步任务外,也可以按照宏任务和微任务来区分。宏任务包括整体代码,setTimeout,setInterval,而微任务包括Promise,process.nextTick。process.nextTick是node环境下的我们暂且不说它。宏任务产生的异步代码会放到下次event loop中,而微任务产生的代码会放到本次event loop的末尾处。我们来用一段代码来演示

// 异步-宏任务
setTimeout(()=>{console.log('timeout')},0);
// 同步
let p = new Promise((resolve,reject)=>{
  console.log('promise');
  resolve();
});
// 异步-微任务
p.then(()=>{
  console.log('resolve');
});
// 同步-宏任务
console.log('同步');

那么这个输出的结果是怎样的的呢,我们再来分析一下,这次已经是第三次手把手分析代码了,明白什么意思吗?

// 首先进入整体代码
// 接着遇到了setTimout,执行它,把它对应的方法放到异步队列【宏任务】里去,等0ms之后再来执行它
// 接着遇到了new Promise,执行它,输出console.log('promise')
// 接着走,遇到了promise的then;执行它,把它对应的代码放到异步队列【微任务】里
// 接着走,遇到了console.log('同步');执行它,输出同步
// ok同步的执行完了,我去异步队列瞅瞅还有啥

// 异步队列

// 【Promise微任务】本次event loop
console.log('resolve');

// 【setTimeout宏任务】下一次event loop
console.log('timeout')

波罗丁的菠萝
886 声望14 粉丝

深林人不知,明月来相照