async函数实在ES2017标准钟引进的,它是generator函数的语法糖,并对generator函数做了以下改进
1、内置执行器:generator函数返回的是迭代器,而async函数内置执行器自动执行迭代器
2、更好的语义:async/await比*和yield语义更清楚,async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
3、返回promise:async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
基本用法:
const promiseData = Promise.resolve('result') // 定义一个promiseconst test1 = async () => {const num = await 6const result = await promiseDatareturn result}const test2 = async () => {const result = await promiseDataconst num = await 6return num}test1().then(val => console.log(val)) // resulttest2().then(val => console.log(val)) // 6
我们可以看到不管await后面接的是普通值还是promise,最后返回的都是promise,前面说过了,async函数是generator函数的语法糖,并且带有执行器,下面我们用asyncTogenerator函数来实现同样的功能
上面例子中,两个async函数我们先改写成generator函数:
const promiseData = Promise.resolve('result') // 定义一个promisefunction * geneTest1() {const num = yield 6const data = yield promiseData}function * geneTest2() {const data = yield promiseDataconst num = yield 6}// const gene1 = geneTest1()// const gene2 = geneTest2()
我们要实现的效果是:
const asyncTogen1 = asyncTogenerator(geneTest1)const asyncTogen2 = asyncTogenerator(geneTest2)asyncTogen1().then(val => console.log(val)) // resultasyncTogen2().then(val => console.log(val)) // 6
实现一个asyncToGenerator,经过asyncToGenerator包装过的generator,就跟async函数一样
// 版本一const asyncToGenerator = (generatorFunc) => {return function(...args) {const gen = generatorFunc.call(this, ...args)let preValueconst next = (result) => {const { done, value } = resultif(!done) {preValue = valuereturn Promise.resolve(value).then(val => next(gen.next(val)),err => next(gen.throw(err)))} else {return Promise.resolve(preValue)}}return next(gen.next())}}// 版本二const asyncToGenerator = (generatorFunc) => {return function(...args) {const gen = generatorFunc.call(this, ...args)let preValuereturn new Promise((resolve, reject) => {let preValueconst step = (key, val) => {let resulttry {result = gen[key](val)} catch (error) {reject(error)}const { value, done } = resultif (done) {resolve(preValue)} else {preValue = valuereturn Promise.resolve(value).then(val => step('next', val),err => step('throw', err))}}return step('next')})}}
