目录
引言
Js 是单线程,多任务执行时会触发进程阻塞问题。所以,Js 有两种任务的执行模式:同步和异步。
同步任务:运行在主线程,先于异步任务执行
异步任务:分为宏任务和微任务,微任务先于宏任务执行
微任务:process.nextTick、Promise.then/ catch/finally、async修饰的函数,默认返回 Promise 对象
宏任务:setTimeout、setInterval、ajax请求、文件读写操作
实操1
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
// await console.log('async21');// 这一行改变'async1 end' 'promise2'输出顺序
}
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
结果:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
解释:
先async 声明俩个函数但未执行;随之执行同步语句 script start;
接着 setTimeout 进入宏任务队列,执行async1() 输出async1 start;
到达await async2() 立即执行async2() 输出 async2;
而后面的语句console.log('async1 end') 进入微任务队列;
继续往后到达 new Promise 开始执行输出promise1;
遇见resolve() 需要通过 .then 得结果,其进入微任务队列,无输出;
(到此,微任务队列有:async1 end,promise2 ;宏任务队列有:setTimeout)
接着同步语句输出script end;
然后,依次输出微任务:async1 end,promise2
然后,依次输出宏任务:setTimeout
async await与微任务 - dnoyeb - 博客园 (cnblogs.com)
实操2
console.log(1);
async function asyFunction () {
console.log(2);
await console.log(3);
await console.log(4);
console.log(5);
return 6
}
new Promise((resolve, reject) => {
console.log(10);
resolve();
}).then(res => {
console.log(11);
})
console.log(7);
setTimeout(() => {
console.log(8)
}, 2000)
setTimeout(() => {
console.log(9)
}, 1000)
asyFunction().then(res => { console.log(res) });
结果:1 10 7 2 3 11 4 5 6 9 8
解释:
首先,执行同步语句,输出1
接着async 声明一个函数但未执行;随之执行 new Promise 输出10,并将.then(11)放进微队列
然后,执行同步语句,输出7;接着俩个 setTimeout 进入宏队列
最后执行前面声明的异步函数,立即输出 2 ,3(类似第一题)
没有输出4是因为前一个await,将其 及后的 .log(5)均放入微队列
接着 return 6 由该异步函数的.then 接住放入微队列
到此,微队列里依次是 11 4 5 6,逐个输出
而宏队列的由延迟时间大小,依次输出 9 8
实操3(nextTick)
1、
setImmediate(function () {
console.log(1);
}, 0);
setTimeout(function () {
console.log(2);
}, 0);
new Promise(function (resolve) {
console.log(3);
resolve();
console.log(4);
}).then(function () {
console.log(5);
});
console.log(6);
process.nextTick(function () {
console.log(7);
});
console.log(8);
// 3 4 6 8 7 5 2 1
2、
//加入两个nextTick的回调函数
process.nextTick(function () {
console.log('nextTick延迟执行1');
});
process.nextTick(function () {
console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
console.log('setImmediate延迟执行1');
// 进入下次循环
process.nextTick(function () {
console.log('强势插入');
});
});
setImmediate(function () {
console.log('setImmediate延迟执行2');
});
console.log('正常执行');
正常执行
nextTick延迟执行1
nextTick延迟执行2
setImmediate延迟执行1
强势插入
setImmediate延迟执行2
3、
console.log("start");
process.nextTick(() => {
console.log("a");
setImmediate(() => {
console.log("d");
});
new Promise(res => res()).then(() => {
console.log("e");
process.nextTick(() => {
console.log("f");
});
new Promise(resolve => {
resolve()
})
.then(() => {
console.log("g");
});
setTimeout(() => {
console.log("h");
});
});
});
setImmediate(() => {
console.log("b");
process.nextTick(() => {
console.log("c");
});
new Promise(res => res()).then(() => {
console.log("i");
});
});
console.log("end");
// start end a e g f h b c i d
总结:
- 同步代码执行顺序优先级高于异步代码执行顺序优先级;
- new Promise(fn)中的fn是同步执行;
- process.nextTick()>Promise.then()>setTimeout>setImmediate。