了解async/await,这篇就够了!

188 阅读2分钟

generator

  • 要想理解async/await, 首页要了解生成器和迭代器,他们的关系是:生成器生成迭代器;
  • js中的生成器就是方法定义加一个星号 *,生成器的执行和普通方法一样,执行结果为迭代器;
  • 执行迭代器通过next方法,返回值为包含value和done两个key值的对象{value: xx, done: true}, 遇到field暂停;
  • next的实参就是上个yield的返回值;
// 定义生成器read
function* read() {
    let a = yield 1
    console.log(a) // 1
    let b = yield a
    return b
}

// 生成迭代器it
let it = read()

// 执行迭代器
let a = it.next()
let b = it.next(a.value)
console.log(it.next(b.value)) // { value: 2, done: true }
  • 通过上面代码我们可以看出,如果生成器中有多个yield,那么我们在执行它的迭代器时,需要多次next,代码比较繁琐,为了解决这个问题,我们写一个co方法,来帮我们next

co

/**
* it为迭代器
*/
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) // 1, 最终拿到b的值
})
  • 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) // 1
})

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())
  • 代码看着很舒服了~