众所周知,JS(ECMA-script)是一门单线程编程语言,单线程的意思就是同一时间只能执行一条任务,当前任务执行完毕之后才会执行下一个任务。
同步任务
同步任务是一个耗时任务,是指在主线程上排队等待执行的任务,只有当主线程上一任务执行完毕之后才会继续执行下一任务。如果上一任务执行完毕需要一小时,下一个同步任务就需要等待一小时才能开始执行。
例如:
function fn1(){
console.log(1)
};
function fn2(){
console.log(2)
};
fn1();
fn2();
//输出的是1,2
//----------------------------------------------------
fn2();
fn1();
//输出的是2,1
js同步代码的执行顺序是从上向下依次执行。
异步任务
异步任务是一个非耗时任务,是不用进入主线程进行等待的任务,在自己的任务队列中,异步任务由js委托给宿主环境进行执行,当异步任务执行完成后会通知js主线程,执行异步任务的回调函数
例如:function fn1(){
console.log(1)
}
function fn2(){
setTimeout(()=>{
console.log(2)
},0)
console.log(3)
}
fn3(){
console.log(4)
}
fn1();
fn2();
fn3();
//输出顺序为:1,3,4,2
执行过程
1.同步任务由js主线程次序执行(执行栈)
2.异步任务:非耗时任务,异步任务由js委托给宿主环境进行执行,当异步任务执行完成后悔通知js主线程执行异步任务的回调函数
3.已完成的异步任务对应的回调函数会被加入到任务队列中等待执行
4.js主线程执行栈被清空后,会读取任务队列中的回调函数,次序执行
5.js主线程会不断地重复第四步
我们常见的异步任务都有:
定时器函数:setTimeout,setInterval;Promise函数
事件函数:例如 onclick,onkeydown...;
ajax的回调函数:onreadystatechange
这些都是在前端中最常见的一些异步任务
异步任务中的宏任务与微任务
宏任务(macrotask)
个人理解:宏任务就是由宿主环境发起的任务,就是宏任务。例如:定时器函数...
微任务(microtask)
个人理解:微任务就是由JS引擎发起的任务,就是微任务。他的执行顺序先于宏任务(Promise.then),他会在宏任务执行过程中,将所有的微任务都执行完毕之后再继续执行下一个宏任务。直接上图:
示例:
setTimeout(function(){
console.log('1');
},0);
new Promise(function(resolve){
console.log('2');
resolve();
}).then(function(){
console.log('3');
}).then(function(){
console.log('4')
});
console.log('5');
//执行顺序:2,5,3,4,1
//先执行Promise这一个同步任务
//再执行console.log(5)这个同步任务中的代码
//然后再是Promise中的.then这两个微任务依次执行
//最后执行异步宏任务,定时器
最后总结JS的执行机制:先同步后异步,异步中:先微任务后宏任务