1.async-await作用
1-1.使用场景
用同步的方式,执行异步操作
例如:有3个请求需要一次进行,而且第2、第3个请求都要用到前一个请求返回的结果
promise实现:
function request(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = param *2
console.log(res)
resolve(res)
}, 1000);
})
}
function dataRequest(param) {
console.log('promise实现:')
request(10).then(res1 => {
request(res1).then(res2 => {
request(res2).then(res3 => {
console.log('请求结束', res3)
})
})
})
}
dataRequest()
async-await实现:
function request(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// console.log(param)
const res = param *2
console.log(res)
resolve(res)
}, 1000);
})
}
async function dataRequest() {
console.log('async-await实现:')
const res1 = await request(10)
const res2 = await request(res1)
const res3 = await request(res2)
console.log('数据请求结束', res3)
}
dataRequest()
1-2.使用注意事项
1-2-1.await只能在async函数中使用,不然会报错。
function request(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = param *2
console.log(res)
resolve(res)
}, 1000);
})
}
function dataRequest() {
await request(10)
}
1-2-2.如果await后面函数的返回值不是一个promise,则起不到排队等待的作用。
function request(param) {
setTimeout(() => {
const res = param *2
console.log(res)
}, 1000);
}
async function dataRequest() {
await request(10)
await request(20)
await request(30)
}
dataRequest()
// 一次性输出20、40、60
1-2-3.async函数的返回值是一个fulfilled状态的promise。
async function dataRequest() {}
console.log(dataRequest())
2.generator函数。
2-1.generator函数简介
在定义一个函数的时候,在函数名前面加上*,此时这个函数就变成了一个generator函数。
例如:
function* gen() {}
2-2. yield
2-2-1. yield 基本使用
只有在 generator 函数中才能使用 yield ,它相当于函数运行过程中的暂停点,想要函数继续下走,需要使用 next 方法。
例如:
function* gen() {
yield console.log(1)
yield console.log(2)
yield console.log(3)
}
const g = gen()
g.next() // 1
g.next() // 2
g.next() // 3
2-2-2. next 方法返回值
next 方法返回一个对象,对象中有 value 和 done 两个属性。
value : yield 后面表达式的返回值。
done : 标志 generator 函数是否已走完,没走完为false,走完为true。
例子:
function* gen() {
yield 1
yield 2
yield 3*3
}
const g = gen()
console.log(g.next()) // { value: 1, done: false }
console.log(g.next()) // { value: 2, done: false }
console.log(g.next()) // { value: 9, done: false }
console.log(g.next()) // { value: undefined, done: true }
function* gen() {
yield 1
yield 2
yield 3*3
return 10
}
const g = gen()
console.log(g.next()) // { value: 1, done: false }
console.log(g.next()) // { value: 2, done: false }
console.log(g.next()) // { value: 9, done: false }
console.log(g.next()) // { value: 10, done: true }
注意:最后一个next的函数值的value属性是否为undefined取决于函数gen是否有返回值。
2-2-3.next函数传参
调用next方法的时候,可以向其中传参,这个参数是yield的返回值。
例子:
function* gen(param) {
console.log(param)
const param1 = yield 1
console.log(param1)
const param2 = yield 2
console.log(param2)
const param3 = yield 3*3
console.log(param3)
return 10
}
const g = gen('-1')
g.next('00')
g.next('11')
g.next('22')
g.next('33')
// -1
// 11
// 22
// 33
注意,第一次调用next时传参无效,从第二次调用next传参才有效。
2-2-4.promise和next传参结合使用
function createPromise(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = param * 2
resolve(res)
}, 1000);
})
}
function* gen() {
const res1 = yield createPromise(1)
const res2 = yield createPromise(res1)
const res3 = yield createPromise(res2)
return res3
}
const g = gen()
g.next().value.then(res => {
console.log(res) // 2
g.next(res).value.then(res => {
console.log(res) // 4
g.next(res).value.then(res => {
console.log(res) // 8
})
})
})
// 2
// 4
// 8
3.实现async-await
3-1.简单实现
function createPromise(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = param * 2
resolve(res)
}, 1000);
})
}
function* gen() {
const res1 = yield createPromise(1)
const res2 = yield createPromise(res1)
const res3 = yield createPromise(res2)
return res3
}
function myAsyncFun(genFun) {
return function() {
return new Promise((resolve, reject) => {
const g = genFun()
g.next().value.then(res => {
console.log(res)
g.next(res).value.then(res => {
console.log(res)
g.next(res).value.then(res => {
resolve(res)
})
})
})
})
}
}
const asyncFun = myAsyncFun(gen)
asyncFun().then(res => {
console.log('res', res)
})
3-2.完善代码
function createPromise(param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const res = param * 2
resolve(res)
}, 1000);
})
}
function* gen() {
const res1 = yield createPromise(1)
const res2 = yield createPromise(res1)
const res3 = yield createPromise(res2)
return res3
}
function generatorToAsync(generatorFn) {
return function() {
const gen = generatorFn.apply(this, arguments) // gen有可能传参
// 返回一个Promise
return new Promise((resolve, reject) => {
function go(key, arg) {
let res
try {
res = gen[key](arg) // 这里有可能会执行返回reject状态的Promise
} catch (error) {
return reject(error) // 报错的话会走catch,直接reject
}
// 解构获得value和done
const { value, done } = res
if (done) {
// 如果done为true,说明走完了,进行resolve(value)
return resolve(value)
} else {
// 如果done为false,说明没走完,还得继续走
// value有可能是:常量,Promise,Promise有可能是成功或者失败
return Promise.resolve(value).then(val => go('next', val), err => go('throw', err))
}
}
go("next") // 第一次执行
})
}
}
const asyncFn = generatorToAsync(gen)
asyncFn().then(res => console.log(res))
参考文献: