generator生成器和promise配合实现看似同步的异步流程控制(async和await)

本文来自于 <你不知道的Javascript> 学习笔记
生成器函数返回的是迭代器,在内部每个yield的是promise,当迭代器启动后,it.next().value就是promise,在promisethen中不断的递归执行 it.next(data) 方法,其中data就是每个promise resolve的值.

es7asyncawait相当于就是把这个流程写进了语法层面.async函数相当于 生成器,await 相当于 yield

function foo() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('一层 promise resolve的值')
        }, 1000)
    })
}

function bar() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(new Promise(resolve => {
                resolve('两层 promise resolve 的值')
            }))
        }, 1000)
    })
}

function syncFn() {
    return '同步函数返回的值'
}

// 这里相当于 async 函数
function* main() {
    try {
        console.log('1', yield foo()) // yield 相当于 await 
        console.log('2', yield bar())
    } catch (err) {
        console.log(err)
    }
    console.log('3', yield syncFn())
    return 'inner value'

}

// 该函数用于自动执行 generator 函数返回的迭代器的 next 方法,直到 done, 在 yield 后面的 promise 的回调中执行 it.next, 递归执行.
function runGenFn(genFn) {
    const it = genFn()
    return new Promise(resolve => {
        // 递归执行迭代器,将 promise resolve 的值传递进生成器里的 yield 
        const _runIt = (it, data) => {
            const { value, done } = it.next(data)

            if (!done) {

                toPlainPromise(value).then(_data => {
                    // console.log('hhh')
                    _runIt(it, _data)
                })
            } else {

                toPlainPromise(value).then(_data => {
                    resolve(_data)
                })
            }
        }

        const isPromise = (v): v is Promise<any> => {
            return Object.prototype.toString.call(v) == '[object Promise]'
        }

        // 解析多层 promise,返回只有一层的 promise
        const toPlainPromise = (p) => {

            const resolveNestPromise = (p, resolve) => {
                if (isPromise(p)) {
                    p.then(value => {// 此处的value可能还是promise
                        resolveNestPromise(value, resolve)
                    })
                } else {
                    resolve(p)
                }
            }

            return new Promise(resolve => {
                resolveNestPromise(p, resolve)
            })
        }

        _runIt(it, undefined)
    })

}

runGenFn(main).then(data => {
    console.log('main 生成器返回的值::>>', data)
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值