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') // 定义一个promise
const test1 = async () => {
const num = await 6
const result = await promiseData
return result
}
const test2 = async () => {
const result = await promiseData
const num = await 6
return num
}
test1().then(val => console.log(val)) // result
test2().then(val => console.log(val)) // 6
我们可以看到不管await后面接的是普通值还是promise,最后返回的都是promise,前面说过了,async函数是generator函数的语法糖,并且带有执行器,下面我们用asyncTogenerator函数来实现同样的功能
上面例子中,两个async函数我们先改写成generator函数:
const promiseData = Promise.resolve('result') // 定义一个promise
function * geneTest1() {
const num = yield 6
const data = yield promiseData
}
function * geneTest2() {
const data = yield promiseData
const num = yield 6
}
// const gene1 = geneTest1()
// const gene2 = geneTest2()
我们要实现的效果是:
const asyncTogen1 = asyncTogenerator(geneTest1)
const asyncTogen2 = asyncTogenerator(geneTest2)
asyncTogen1().then(val => console.log(val)) // result
asyncTogen2().then(val => console.log(val)) // 6
实现一个asyncToGenerator,经过asyncToGenerator包装过的generator,就跟async函数一样
// 版本一
const asyncToGenerator = (generatorFunc) => {
return function(...args) {
const gen = generatorFunc.call(this, ...args)
let preValue
const next = (result) => {
const { done, value } = result
if(!done) {
preValue = value
return 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 preValue
return new Promise((resolve, reject) => {
let preValue
const step = (key, val) => {
let result
try {
result = gen[key](val)
} catch (error) {
reject(error)
}
const { value, done } = result
if (done) {
resolve(preValue)
} else {
preValue = value
return Promise.resolve(value)
.then(
val => step('next', val),
err => step('throw', err)
)
}
}
return step('next')
})
}
}