js
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
});
async1();
console.log('script start');
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
输出:
script start
async1 start
async2
script start
promise1
async1 end
promise2
setTimeout
js是一个单线程,会阻塞代码
为了防止阻塞代码,把代码分为同步和异步
同步代码交给js引擎执行(js只能是单线程)
异步代码交给宿主环境(浏览器/node,可以支持多线程)
同步代码放到执行栈,异步代码等时机成熟会放到任务队列里
执行栈执行完,会去任务队列看是否有异步任务,有就推送到执行栈执行,反复循环查看执行,这个过程就是事件循环(eventloop)
1.同步任务和异步任务
1.定时器
js
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
console.log(3)
输出:132
js是单线程的,同一时间只能做一件事
作为浏览器脚本语言,与它的用途有关
js主要用途是和用户互动,以及操作DOM,这决定了它只能是单线程
例如如果线程1和线程2分别是添加和删除同一个节点,执行顺序不同会导致结果的不同
所以只能先添加再删除

总不能等计时器结束才执行吧,总不能等到事件监听点击之后才执行吧

异步代码的共同点:它们都是耗时的

同步代码放到执行栈,异步代码放到宿主环境
执行栈:里的代码立即执行,并且原地等待结果
宿主环境的时间一到,就推送到任务队列
执行栈执行完了,就会看任务队列有没有异步任务需要执行
此时再把任务队列的异步函数的回调函数推送到执行栈
执行栈只要同步代码一执行完,就会反复到任务队列去看有没有异步的任务需要执行
从执行栈到任务队列反复查找的过程就叫事件循环



2.异步任务(宏任务/微任务)
js把异步任务分为宏任务和微任务
ES5之后,js引入了Promise
这样,即使不需要浏览器,js引擎自身也能发起异步任务
宏任务由宿主(浏览器、Node)发起
微任务由JS引擎发起
主要的异步任务有Promise
不过Promise本身同步,里面的then/catch的回调函数是异步的




代码示例
js
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
const p = new Promise((resolve, reject) => {
console.log(3);
resolve(1000); // 标记为成功
console.log(4);
});
p.then(data => {
console.log(data);
});
console.log(5);
输出:1 3 4 5 1000 2
js
new Promise((resolve, reject) => {
resolve(1);
new Promise((resolve, reject) => {
resolve(2);
}).then(data => {
console.log(data);
});
}).then(data => {
console.log(data);
});
console.log(3);
输出:3 2 1
js
console.log(11);
setTimeout(() => {
console.log(12);
let p = new Promise((resolve) => {
resolve(13);
});
p.then(res => {
console.log(res);
});
}, 0);
console.log(15);
console.log(14);
输出:11 15 14 12 13
js
setTimeout(() => {
console.log(1);
}, 0);
new Promise((resolve, reject) => {
console.log(2);
resolve('p1');
})
new Promise((resolve, reject) => {
console.log(3);
setTimeout(() => {
resolve('setTimeout2');
console.log(4);
}, 0);
resolve('p2');
}).then(data => {
console.log(data);
});
setTimeout(() => {
resolve('setTimeout1');
console.log(5);
}, 0).then(data => {
console.log(data);
});
console.log(6);
js
setTimeout(() => {
console.log(1);
}, 0);
new Promise((resolve, reject) => {
console.log(2);
resolve('p1');
new Promise((resolve, reject) => {
console.log(3);
setTimeout(() => {
resolve('setTimeout2');
console.log(4);
}, 0);
resolve('p2');
}).then(data => {
console.log(data);
})
setTimeout(() => {
resolve('setTimeout1');
console.log(5);
}, 0)
}).then(data => {
console.log(data);
});
console.log(6);
输出:2 3 6 p2 p1 1 4 5
定时器里的resolve('setTimeout2')、resolve('setTimeout1')是迷惑性的
promise里有resolve,定时器里是不执行的
async函数里的代码属于同步任务,await后面所有的代码,在函数后面的所有代码都属于微任务,等代码执行完了才去执行
js
async function async1() {
console.log('async1 start');
await async2(); //await下面的代码暂时是不执行的,除非右边全部执行完了才会去执行
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0);
async1();
输出:script start/async1 start/async2/async1 end/setTimeout