Generator

简介:

生成器,本身是函数,执行后返回迭代对象,函数内部要配合yield使用Generator函数分段执行,遇到Yields即暂停

特点:

function和函数名之间需要带*

函数体内部Yield表达式,产出不同的内部状态

function* test() {
    let value1 = yield 'a'
    console.log(value1)
    let value2 = yield 'b'
    console.log(value2)
    yield 'c'
    yield 'd'
    return 'e'
}

let oG = test()

oG.next('chen') //因为执行完yield之后会暂停,所以后边的赋值语句不会进行,类似一个蛇形样子

现在我们要实现一个场景:
这个场景是去name.txt文件中读取一个文件路径’./number.txt’,然后在number.txt文件中读取到最终的数字

这个是公共代码部分,稍后还会继续用到

const fs = require('fs')
function readFile(path) {
    return new Promise((res, rej) => {
        fs.readFile(path, 'utf-8', (err, data) => {
            if (err) {
                return rej(err)
            } else {
                return res(data)
            }
        })
    })
}

我们最初会有这么一个思路:直接嵌套调用。但是如果嵌套多了之后是不是很不舒服,代码看起来也不优雅。

readFile('./name.txt').then(res => {
    readFile(res).then(res => {
        console.log(res)
    })
}).catch(err => {
	// 省略,不是重点
})

现在我们可以借用Generator去实现:

// 进行封装的原因是yield的调用是暂停的,不连续
function Co(oG) {
    return new Promise((res, rej) => {
        let next = (data) => {
            let { value, done } = oG.next(data)
            if (done) {
                res(value)
            } else {
                value.then(val => {
                    next(val)
                }).catch(err => {
                    return rej(err)
                })
            }
        }
        next()
    })
}

function* read() {
	// 并非是把迭代对象{value: '', done: ''}付给了value1
	// 封装Co正是为了解决这个问题
    let value1 = yield readFile('./name.txt')
    let value2 = yield readFile(value1)
    return value2
}

// 最终只需这样调用,对于之后开发的类似场景就直接调用即可
Co(read()).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

其实await + async语法糖对其进行了进一步的封装,可以参靠文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章