性格严肃的人跳过这一段,皮百万的不用。
最近,在一次正式场合下,遇到了一道检验js相关原理的题目,当时虎躯一震,这不是送分儿咩?不由分说,大笔一挥,写完之后还骄傲的叉了会儿腰,大概是这样事儿的:
(膨胀使我头大)
完事儿之后,似乎略有不妥,但是作为快乐风男,前进的道路上绝不回头,纵使身后洪水滔天。然而缘分就是这么巧,一个非正式场合下,再次相遇,怎么能放过人前显圣的机会(读书人装逼不叫装逼,叫人前显圣)?一顿键盘后,准备再叉会儿腰,然而正确答案让我猝不及防。。。
async function async1() {
console.log(1)
const result = await async2();
console.log(3)
}
async function async2() {
console.log(2);
}
Promise.resolve().then(() => {
console.log(4)
})
setTimeout(() => {
console.log(5)
})
async1();
console.log(6);
请写出打印结果。对于相关原理不太了解的同学,想来是要翻车的;有点了解的同学,指定会是一副激动的心、颤抖的手,插着腰,敲出162345。然而正确答案:
结果是意外的,这波儿腰就先别插了,咱们象征性的分析分析,这是啥原因。
根据这道题的呈现,可以看出,涉及到的基本原理有以下几个方面:
每一个方面其实都包含不少的知识,在这里就不一一细讲了,毕竟网上到处都是(不是不想讲,也不是不会讲,只是之前有同学评论我,都9102年了,再写这种基础活该挨骂。我这向来都是从善如流,虚心听取)。所以咱们只讲涉及到的。
首先,同步异步就很常见了,一笔带过,同步,从上到下,从左到右,按顺序执行code;异步,code执行到该行为时,先收集起来,暂不执行,等到执行时机到来,在执行队列里收集到的行为。
然后,宏任务微任务,简单来说,均属异步行为,一般情况下,一个宏任务里面总是先顺序执行同步代码,再顺序执行该宏任务中的微任务(嵌套的话,会更复杂一些),等到都执行完毕,再进入下一个宏任务。啥是宏任务?script标签包含的code、setTimeout、setInterval、setImmediately、I/O等。啥是微任务?promise.then、process.nextTick等。
接着,promise,一个处理异步行为的工具,属于微任务,例题中相关代码为:
Promise.resolve().then(() => {
console.log(4)
});
怎么理解这段代码?Promise.resolve()返回了一个promise对象(也叫thenable对象),并且这个对象立马被resolve。但是由于resolve函数里面的code是一个异步的行为,所以尽管resolve是在then之前执行,但是,里面的异步行为是排在then执行之后才触发。(异步行为=》执行当前promise实例中存放then方法收集到的函数队列,这个队列是一个微任务队列), 然后这个对象的then方法收集了一个回调函数,放在promise实例的微任务回调队列里(then只是收集,并没有执行,是resolve的执行,才触发了微任务异步队列的执行),then会返回一个新的promise实例,但是这个这里不涉及,暂且不表。
最后,async-await,这道题里涉及到两个很关键的概念:
执行这段代码,理解上述说明:
var o = {};
o.__proto__.then = function(resolve,reject){
resolve(1);
};
(async ()=>{
var r = await o;
console.log(r);
})();
注意:thenable对象中被注入的resolve函数,如果不执行,那么await将一直阻塞,当前作用域里,await后面的代码永远不会执行。
await会如我们分析的这样去做么?它会和promise的微任务队列这样配合?
我们直接写一个例子试一下:
async function async1() {
console.log(1)
const result = await async2();
console.log(3)
}
async function async2() {
console.log(2);
return {
then:(res)=>{
console.log(7);
res();
}
}
}
Promise.resolve().then(() => {
console.log(4)
})
setTimeout(() => {
console.log(5)
})
async1();
console.log(6)
根据我们上面讲的原理,结果应该是1,2,6,4,7,3,5。你去打印试试吧,在谷歌里哦,防止翻车~
需要声明的一点是,我不是一个教授者,我只是一个分享者、一个讨论者、一个学习者,有不同的意见或新的想法,提出来,我们一起研究。分享的同时,并不只是被分享者在学习进步,分享者亦是。
知识遍地,拾到了就是你的。