简介:
生成器,本身是函数,执行后返回迭代对象,函数内部要配合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语法糖对其进行了进一步的封装,可以参靠文章