ES6 Generator概念的引入,虽然从本质上讲是一个“语法糖”的概念,但它完全放飞了“异步函数设计”和“协程设计”两个领域,本文从一个实例的角度分析了它的使用过程。
海南儋州市海花岛灯光秀--2022-1
1. 使用《回调函数》设计的generator函数
/**
* 异步函数gen(也可理解为协程)中调用《回调函数版本的异步函数》
* 优点是调用方式同步化(在main中)
* 缺点是使用闭包获取generator对象,来完成回调中的next()
*/
let fs=require('fs')//引入回调函数版的fs模块
function* gen(filename){
/*
gen函数的第一段(发起异步调用)
*/
console.log("马上就要进行文件读取。。。")
let fileContent=yield fs.readFile(filename,'utf-8',(err,data)=>{
if(!err){
//需要以闭包的方式获取generator对象
closureGen.next(data)//data将成为yield fs.readFile的返回值
}
})
/*
gen函数的第二段(回调处理)
*/
console.log(fileContent)
console.log("文件内容读取完毕。。。")
}
function main(){
let closureGen=gen('./test1.rest')
//如没有此行,则gen函数从定义的位置去查询closureGen,则无法查到闭包环境中的closureGen
//当然也可以将gen函数定义为main函数的内部函数,从而closureGen成为闭包环境变量
global.closureGen=closureGen
closureGen.next()
}
main()
2. 使用《Promise》设计的generator函数(鼓励使用!)
/**
* 异步函数gen(也可理解为协程)中调用《Promises版本的异步函数》
* 优点是gen函数中的实现非常自然(只有加入yield关键字的成本),同时不必关心闭包变量(generator对象)的问题
* 缺点是在调用时,需要使用promise语法,同时也需要熟悉generator对象的next方法的传参技巧
*/
const fs=require('fs/promises')//promise版本的fs模块
function* gen(filename){
/*
gen函数的第一段(发起异步调用)
*/
console.log("马上就要进行文件读取。。。")
let fileContent=yield fs.readFile(filename,'utf-8')
/*
gen函数的第二段(回调处理)
*/
console.log(fileContent)
console.log("文件读取完毕。。。")
}
function main(){
let g=gen("./test1.rest")
g.next().value
.then(data=>{
g.next(data)
})
}
main()
3. 使用《co》进行调用时封装的《Promise》版本
/**
* 此版本gen的实现与Promise版本完全一致,但引入co库,解决调用代码的复杂度
*/
const co=require('co')//引入TJ的cooperate库
const fs=require('fs/promises') //promise版本的fs模块
function* gen(filename){
//内容与promise版本完全一至
}
function main(){
co(gen,"./test1.rest")
}
main()
网友评论