async函数和genorator函数
总述:Async函数就是genorator函数的语法糖,他是genorator函数+一个自动执行器,包含在一个函数里。
1.genorator函数
这里概念就不多说了,为了解决异步编程的方法之一,我直接上代码
请复制以下代码到编辑器中运行或查看,会更加清晰
function base(){
console.log('hello1')
}
const fn = function* (){
let res = yield base()
console.log('res',res) //第一次调用时,遇到yield关键字就停下了,第二次调用时,不会重复执行yield这句语句,所以res是undefine
return 'done'//yield都能返回语句后面的表达式的值,却别就是return没有记忆功能
}
let f = fn() // 返回Iterator对象,使用Iterator的next方法,遍历
f.next() // hell1
let done = f.next()
console.log(done) // res undefined; {value: "done", done: true}
// done为true时,表示遍历结束,如何返回fasle说明还要继续遍历
// 如果遍历第2次的时候, f.next(1),在next中传值,这个值就是作为第一次遍历yield返回的结果赋值给res,next参数表示上一个yield表达式的结果
查看上面的代码和逻辑图,相信你已经有所收获了,但是我觉得有道题可以让你再次巩固一下:
练习(请复制代码到编辑器,并且思考之后再自行打印答案):
function* gen(x) {
let y = 2 * (yield (x + 1)) // 注意:yield 表达式如果用在另一个表达式中,必须放在圆括号里面
let z = yield (y / 3)
return x + y + z
}
let it = gen(5)
console.log(it.next()) // ?
console.log(it.next(9)) // ?
console.log(it.next(2)) // ?
应用:长轮训
function* ajax() {
yield new Promise((resolve, reject) => {
// 此处用一个定时器来模拟请求数据的耗时
setTimeout(() => {
resolve({code: 0})
}, 200)
})
}
// 长轮询的方法
function update() {
let promise = ajax().next().value // 返回的对象的value属性是一个 Promise 实例对象
promise.then(res => {
if(res.code != 0) {
setTimeout(() => {
console.log('2秒后继续查询.....')
update()
}, 2000)
} else{
console.log(res)
}
})
}
2.async函数
是genorator函数的语法糖,自带执行器,不需要使用next方法才能拿到结果。
异步编程的终极解决方案,意思是说,大部分的情况下,能用genorator函数的,都可以使用async函数。
示例:
async function fn(){
const res1 = await login();
const res2 = await getUserInfo(res1)
const res3 = await getProductInfo(res2)
}
以上是业务很常见的情景,用户未登录要先登录之后才能获取用户信息,获取完之后,才能获取商品的相关信息。
优势:
1.语义更加清晰,async表示有异步事务,await后面语句表示需要等待的结果
2.更广的适用性,await后面可以接受promise和原始类型的值
3.自带执行器,不用调用next方法才能拿到结果
4.返回值是Promise,可以使用then或catch处理
3.async函数对比callback
避免了阻塞,
避免了回调及可能遇到的回调地狱,
避免每个任务都要调用一个回调函数