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語法糖對其進行了進一步的封裝,可以參靠文章

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