async await 语法是手写 ES7出现的,是核心基于ES6的 promise和generator实现的。 这里就不再赘述generator,原理原理专门的再也文章讲专门的内容。 我们先看看下面这代码,不怕这是async await的最简单使用,await后面返回的面试是一个Promise对象: async function getResult() { await new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) } 但不知你有没有想过一个问题,为什么会等到返回的官问promise的对象的状态为非pending的时候才会继续往下执行,也就是手写resolve执行之后,才会继续执行,核心就像下面的原理原理代码一样。 async function getResult() { await new Promise((resolve,再也 reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) console.log(2); } 可以看到运行结果是先打印了1,再打印2了,不怕也就是站群服务器面试说明在返回的promise对象没执行resolve()前,就一直在await,官问等它执行。手写然后再执行下面的程序,那这个是怎么实现的呢? 我们看一下下面的代码,输出顺序是什么? async function getResult() { await new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) await new Promise((resolve, reject) => { setTimeout(() => { resolve(2); console.log(2); }, 500); }) await new Promise((resolve, reject) => { setTimeout(() => { resolve(3); console.log(3); }, 100); }) } 没错是 1,2,3.。 那用generator函数专门来实现这个效果呢? 我一开始这样来实现: function* getResult(params) { yield new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(2); console.log(2); }, 500); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(3); console.log(3); }, 100); }) } const gen = getResult() gen.next(); gen.next(); 但是发现打印顺序是 3,2,1.明显不对。 这里的问题主要是三个 new Promise几乎是同一时刻执行了。才会出现这种问题,所以需要等第一个promise执行完resolve之再执行下一个,所以要这么实现。 function* getResult(params) { yield new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(2); console.log(2); }, 500); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(3); console.log(3); }, 100); }) } const gen = getResult() gen.next().value.then(() => { gen.next().value.then(() => { gen.next(); }); 可以看到这样就打印正常了。 但是呢,源码库总不能有多少个await,就要自己写多少个嵌套吧,所以还是需要封装一个函数,显然,递归实现最简单。 function* getResult(params) { yield new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(2); console.log(2); }, 500); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(3); console.log(3); }, 100); }) } const gen = getResult() function co(g) { g.next().value.then(()=>{ co(g) }) } 再来看看打印结果: 可以发现成功执行了,但是为什么报错了? 这是因为generator方法会返回四次,最后一次的value是undefined。 而实际上返回第三次就表示已经返回done,代表结束了,所以,我们需要判断是否是已经done了,不再让它继续递归。 所以可以改成这样: function* getResult(params) { yield new Promise((resolve, reject) => { setTimeout(() => { resolve(1); console.log(1); }, 1000); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(2); console.log(2); }, 500); }) yield new Promise((resolve, reject) => { setTimeout(() => { resolve(3); console.log(3); }, 100); }) } const gen = getResult() function co(g) { const nextObj = g.next(); if (nextObj.done) { return; } nextObj.value.then(()=>{ co(g) }) } 可以看到这样就实现了。 完美,这个co其实也是大名鼎鼎的co函数的简单写法。 本篇文章关于async 和 await的原理揭秘就到此为止了,再讲下去就不礼貌了。前言
generator函数
await在等待什么