簡介:
生成器,本身是函數,執行後返回迭代對象,函數內部要配合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語法糖對其進行了進一步的封裝,可以參靠文章