JS-知识盲区 | async & await的认识

83 阅读2分钟

async await的执行流程

一直没有关注await这个关键字,只知道await如何使用、await是类似于resolve成功回调的作用,以前的实现中通过 new Promise(resolve => resolve()),但是在优化以后变为了Promise.resolve()。在面试时做到有关于事件循环的问题。 下面的问题不涉及到 async和Promise的优先级判断,只是普通的同步异步判断,用来重新认识Generator+Promise == async 与 await 的过程

setTimeout(() => {console.log(0)}, 0)
{ //Node 不允许直接写自执行匿名函数,应该放在大括号内
	(async function(){
		console.log(1)
		await Promise.resolve()
		console.log(2)
	})()
}

console.log(3)

new Promise(reslve => {
	console.log(4)
}).then(res => {
	console.log(5)
}).catch(err => {
	console.log(6)
})


const p = new Promise((resolve, reject) => {
	console.log(7)
	resolve(8)
})

p.then(res => {
	console.log(res)
}).then(res => {
	console.log(9)
})
p.then(res => {
	console.log(10)
})

{
	(async () => {
		console.log(11)
		await Promise.resolve(333)
		console.log(12)
	})()
}

解析

注意:async修饰的函数是一个同步执行的函数,但是当遇到了await,await后的所有代码块变为了微任务,如果再遇到了await,此时是上一个await的then中的任务,也就是微任务,此时能够从生成器和Promise结合中进行解释。

复习生成器

使用 function* 定义,特殊的在类中的另外一种语法*[Symbol.iterator](){} || *iterator(){}也是可以的。通过关键字yield分割代码块,通过关键字yield分割的代码块类似一个一个的函数。

  • 生成器是特殊的迭代器
  • 通过yield控制代码运行,yield类似函数,能够接收和返回。 const msg = yield 'Hello JS'
function request(msg) {
	return new Promise((resolve, reject) => {
		resolve(msg)
	})
}
function* getBanners() {
 // 每一次的yield都代表着then链式的代码块
 let msg = yield "Hello JS";
 msg = yield request(msg + "aaa");
 msg = yield request(msg + "bbb");
 msg = yield request(msg + "ccc");
 console.log(msg);
}
// 手动实现,将每一个步骤都和Promise联系起来
const generator = getBanners("Hello JS");
Promise.resolve(generator.next().value).then((res) => {
 generator.next(res).value.then((res) => {
   generator.next(res).value.then((res) => {
     generator.next(res).value.then((res) => {
       generator.next(res); // 最后可以进行调用
     });
   });
 });
});

// 自动实现(递归方式有多少次yield,就进行计算)
let val = generator.next().value /* 初始next */
function co(generator) {
 if (val === undefined) { /* base case */
   return ;
 }

 if (val instanceof Promise) {
   val.then(res => {
     val = generator.next(res).value
     co(generator)
   })
   return ;
 }
 val = generator.next(val).value
 co(generator)
}
co(generator)
  • 经过解析这一阶段,基本上也就是实现了async和await的功能,简单来说yield就是await的功能,同时也能够从实现中发现,await就是类似resolve的语法糖,如果是普通的值那么包裹一层Promise.resolve即可完成Promise对象的转化。
  • 总结:async 与 await == Promise + Generator await后面的代码都会变成微任务的形式。

答案

最主要的还是async和await的同步的异步(微任务,比Promise优先级更高)。

1
3
4
7
11
2
8
10
12
9 注意:这里是因为箭头函数返回最后一行,有返回值,即使没有显式的resolve
0