# generator及co库原理
# generator的基础用法
我们先来看下generator
的基本用法
function* read() {
console.log(1)
yield 1
console(2)
yield 2
return 3
}
let it = read()
it.next() // 1
it.next() // 2
generator
叫生成器,用来生成迭代器(it),我们需要通过调用it.next
让迭代器往前走一步,遇到yield
就会停止
我们在来看一个例子
function* read() {
let a = yield 1
console.log(a) //hello
let b = yield 2
console.log(b) //chenying
return b
}
let it = read()
it.next()
it.next('hello')
it.next('chenying')
我们可以发现,第一次调用next
传进去的参数是无效的,从第二个next
开始传入的参数会作为上一个yield
的返回值,如上述代码中第二个next
传入的参数hello
会作为上一个yeild
的返回值,也就是赋值给a
另外it.next()
会返回一个对象{ value: xxx, done: false/true }
, value
是值,done
表示是否运行到最后
# generator的应用
我们可以通过generator
+ promise
实现异步调用,同样的需求,我们需要读取name.txt
的内容,然后根据这个内容读取对应文件夹的值
我们可以这样来实现
let fs = require('fs').promises
function* read() {
try {
let content = yield fs.readFile('./name.txt', 'utf8')
let age = yield fs.readFile(content, 'utf8')
return age
} catch(e) {
console.log(e)
}
}
let it = read()
let { value } = it.next()
value.then((data) => { //age.txt
let { value } = it.next(data)
value.then((data) => {
let { value } = it.next(data)
console.log(value)
})
})
通过手动的next()
就可以实现这类型的需求,但是我们可以发现代码中有很多重复的部分,这个我们可以用co
库来简化代码
# co库
我们直接使用CO
库来简化下代码
let fs = require('fs').promises
function* read() {
try {
let content = yield fs.readFile('./name.txt', 'utf8')
let age = yield fs.readFile(content, 'utf8')
return age
} catch(e) {
console.log(e)
}
}
co(read()).then(data => {
console.log(data)
})
我们可以发现使用co
库之后代码变得非常的清晰
那我们最后来实现一个这个co
库吧
function co (it) {
return new Promise((resolve, reject) => {
function next (data) {
let { value, done } = it.next(data)
if (!done) {
Promise.resolve(value).then((data) => {
next(data)
}, reject)
} else {
resolve(value)
}
}
next()
})
}
关键核心点在于next
函数,这个思路在很多框架中也有体现(koa,express)