generator
- 要想理解async/await, 首页要了解生成器和迭代器,他们的关系是:生成器生成迭代器;
- js中的生成器就是方法定义加一个星号 *,生成器的执行和普通方法一样,执行结果为迭代器;
- 执行迭代器通过next方法,返回值为包含value和done两个key值的对象{value: xx, done: true}, 遇到field暂停;
- next的实参就是上个yield的返回值;
function* read() {
let a = yield 1
console.log(a)
let b = yield a
return b
}
let it = read()
let a = it.next()
let b = it.next(a.value)
console.log(it.next(b.value))
- 通过上面代码我们可以看出,如果生成器中有多个yield,那么我们在执行它的迭代器时,需要多次next,代码比较繁琐,为了解决这个问题,我们写一个co方法,来帮我们next
co
function co(it) {
return new Promise((resolve, reject) => {
function next(data) {
let {value, done} = it.next(data)
if(done) {
resolve(value)
} else {
Promise.resolve(value).then(next, reject)
}
}
next()
})
}
co(read()).then(value => {
console.log(value)
})
- async/await 可以看作语法糖,是generator+co的实现
- 是async/await出现的时候了, 让我们重新组织下代码执行
async function read(){
let a = await 1
let b = await a
return b
}
read().then(r=>{
console.log(r)
})
promise写多层调用,代码也不好看,可以使用async/await
- 假如现在有需求,是拿到name.txt文件的内容,找到以该内容命名的js文件的内容
- 如果用promise实现
let fs = require('fs').promises
let path = require('fs')
fs.readFile(path.resolve(__dirname, 'name.txt')).then(data => {
fs.readFile(path.resolve(__dirname, `${data}.js`)).then(data => {
console.log(data)
})
})
- 可以看到,此时请求了两个文件,如果有多个文件嵌套获取时,代码也是不好看的,这时可以用async/await像写同步代码一样来实现
let fs = require('fs').promises
async function read() {
let content = await fs.readFile(path.resolve(__dirname, 'name.txt'))
let value = await fs.readFile(path.resolve(__dirname, content + '.js'))
return value
}
console.log(read())