yinanchen
前端开发工程师
yinanchen 2022-05-30
async await 其实是用同步的方式解决,解决异步的操作,举个例子
eg. 先请求接口1后用接口1的数据去请求接口2
// request => Promise
request(1).then(res1 => {
console.log(res1)
request(res1).then(res2 => {
console.log(res2)
})
})
//如果多个接口嵌套,就像重回回调地狱一样
用async await是什么样?
async function fn() {
const res1 = await request(1)
const res2 = await request(res1)
console.log(res2)
}
代码的执行逻辑是怎么样的呢?很简单,跟平常js同步代码执行一致
request(1)
,await
等待请求结束拿到结果res1
res1
结果后再执行request(res1)
等待请求结束拿到res2其实async await 的执行就有点像排队,在async函数中,await关键字规定异步操作只能一个一个的排队执行,从而达到用同步的方式,执行异步的操作
async await是基于generator函数的语法糖
javascript表示集合的数据结构
数组Array
对象Object
Map
Set
需要一种统一的接口机制,来处理不同的数据结构----iterator诞生
Iterator遍历器是一种接口,为不同的数据结构提供统一的访问机制;任何数据结构只要部署了iterator接口,就可以完成遍历的操作
iterator的遍历过程
Js原生具备Iterator接口的数据结构有以下:
这些数据结构的原型中有一个[Symbol.iterator]属性,是一个函数,函数执行返回的是一个Iterator
Iterator中有一个next方法,调用这个方法可以将Iterator的指针指向下一个遍历元素,并且得到返回值,
返回值是一个包裹着value属性(数据结构遍历的元素值)和一个done属性(表示当前遍历的状态,布尔值)
Iterator其实本质就是一个有着一个next(一个指针函数)属性的对象,举个示例
const iterator = [1,2][Symbol.iterator]() // 返回一个iterator
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: undefined, done: true}
协程,意思就是多个线程互相协作,完成异步任务
协程有点像函数,又有点像线程。它的运行流程大致如下。
A
开始执行。A
执行到一半,进入暂停,执行权转移到协程B
。B
交还执行权。A
恢复执行。什么是Generator函数?
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
从形式上讲,generator函数就是一个普通函数,但是有2个特征
function
关键字与函数名之间有一个星号yield
表达式,定义不同的内部状态function* gen() {
yield 1
return 2
}
const g = gen() // generator函数, g是一个iterator遍历器
g.next() // {value: 1, done:false}
g.next() // {value: 2, done:true}
generator函数的执行不会像普通函数执行得到函数内部return的的结构,generator函数的执行会返回一个指向内部状态的指针对象,也就是上面所介绍的Iterator遍历器对象
gennerator函数执行后,必须调用遍历器的next方法,才能使指针移向下一个状态。也就是说,每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
表达式(或return
语句)为止
next
方法的运行逻辑如下。
yield
表达式,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value
属性值。next
方法时,再继续往下执行,直到遇到下一个yield
表达式。yield
表达式,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
属性值。return
语句,则返回的对象的value
属性值为undefined
yield
表达式后面的表达式,只有当调用next
方法、内部指针指向该语句时才会执行,有点类似js里面的惰性求值了(lazy)
function* gen() {
const a = yield 1
console.log(a)
return 2
}
const g = gen()
g.next() // {value: 1, done:false}
g.next() // 先打印 undefined 后打印{value: 2, done:true}
想要yield 1
拥有返回值,该怎么做?
next函数的参数就作为yield表达式的返回值
function* gen() {
const a = yield 1
console.log(a)
return 2
}
const g = gen()
g.next() // {value: 1, done:false}
g.next(6) // 先打印 6 后打印{value: 2, done:true}
const fn = (num) => {
return new Promise(resolve => {
resolve(num)
})
}
function* gen() {
yield fn(1)
return 3
}
const g = gen()
const next1 = g.next() // {value: Promise { <pending> }, done: false}
next1.value.then((res1) => {
console.log(res1)
})
基于上方的generator函数
的yield 语句后接Promise和next传参
,就很像async/await
了,区别在于
return 一个Promise即可
function asyncFn() {
return function() {
return new Promise((resolve,reject) => {})
}
}
function asyncFn(gen) {
return function() {
return new Promise((resolve,reject) => {
const g = gen()
g.next().value.then(res => {
g.next(res)
})
})
}
}
function asyncFn(gen) {
return function () {
return new Promise((resolve) => {
const g = gen()
function next(res) {
const { value, done } = g.next(res)
if (done) {
return resolve(value)
} else {
return value.then((val) => next(val))
}
}
next()
})
}
}