首先需要明白什么是Event Loop?Event Loop就是计算机系统的一种运行机制。JavaScript就是采用的这种机制 ,来解决单线程运行带来的一些问题。
1. JavaScript为什么是单线程的?
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。举个例子:假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这样就会出现一些问题。
2. 任务队列
单线程就意味着所有的任务都需要排队执行,只有上一个任务执行完才会执行下一个任务。如果上一个任务执行耗时很长,那下一个任务就得一直等着。如果是因为任务工作量比较大导致CPU忙不过来了,那等着就等着吧,但是很多时候CPU也是空闲的,这样就会有点不太妥。所有任务分为了两种:同步任务和异步任务。
同步任务就是在主线程上执行,形成一个执行栈,只有上一个任务执行完下一个任务才会开始。
异步任务就是不进入主线程而进入子线程,它不会影响主线程的工作,主线程会照常执行。而当异步任务有的结果后,比如AJAX获取到数据了,那么回调函数就会被放到 任务队列(task queue) 中。
当主线程的 执行栈 所有的同步任务执行完毕后,那么系统就会读取 任务队列,任务队列是一个先进先出的队列,就会将任务队列中的回调函数拿到主线程去执行。
3. 宏任务和微任务
对于异步任务又分为宏任务和微任务
宏任务
宏任务包含:script标签中整体的代码块,setTimeout、setInterval等…
微任务
微任务包含:Promise.then()、$vue.nextTick等…
async await
async await是ES7的语法,async要写在一个函数声明的前面,表明这个函数是一个异步函数;await要搭配async组合使用,写在async函数内部,相当于是将await后面紧跟的异步函数变成的了同步的。
- 对于await,await执行完后面的函数之后,下面的同步逻辑会被 放到该轮微任务执行栈的最后。
理解
对于我自己的理解,当JavaScript在执行时,相当于是有三个执行栈,一个是同步执行栈:所有代码从上到下依次执行,上一步会阻塞下一步的运行。二是微任务执行栈:JavaScript由上到下依次执行,当碰到微任务时会将这个回调函数放到微任务执行栈中。三是宏任务执行栈JavaScript由上到下依次执行,当碰到宏任务时会将这个回调函数放到宏任务执行栈中。当同步执行栈代码执行完毕时,系统会到微任务执行栈中找,当微任务执行栈的任务执行完毕后再执行宏任务执行栈中。
例子
console.log('1')
setTimeout(function () {
console.log('2')
});
new Promise(function (resolve) {
console.log('3');
resolve();
}).then(function () {
console.log('4')
setTimeout(function () {
console.log('5')
});
});
new Promise(function (resolve) {
console.log('6');
resolve();
}).then(function () {
console.log('7')
setTimeout(function () {
console.log('8')
});
});
async function aaa() {
function fun1 (num) {
console.log(num)
}
new Promise((res) => {
fun1(3);
res(4)
}).then((res) => {
fun1(res);
})
await fun1(1);
fun1(2)
}
aaa();
async function aaa() {
function fun (num) {
console.log(num)
}
new Promise((res) => {
fun(3);
res(4)
}).then((res) => {
fun(res);
})
setTimeout(() => {
fun(5);
},0)
await fun(1);
fun(2)
}
aaa();
async function async1() {
console.log(1)
await async2()
console.log(2)
}
async function async2() {
console.log(3)
}
console.log(4)
setTimeout( e =>{
console.log(5)
},0)
async1()
new Promise( res =>{
console.log(6)
res()
}).then( e => {
console.log(7)
})
console.log(8)
|