一,前言
上篇,主要介绍了 generator 生成器函数的使用和实现原理,主要涉及以下几个点:
generator 简介:特性、用法、功能分析;
generator 实现原理分析;
前面的 Promise 仅仅是对异步回到进行了优化,在 Promise 的内部依然还是存在回调的,所以实际上并没有解决“回调地狱”的问题;
最终解决方案还要使用 async/await,async/await 是基于 generator 的语法糖,而为了搞清楚 async/await 的原理,需要先对 generator、co 进行了解;
本篇,继续介绍 co 库:自动执行 Generator 生成器函数;
二,co 库的简介
1,co 库的作用
2,co 库的使用
const util = require('util');
const fs = require('fs');
let readFile = util.promisify(fs.readFile)
// generator 生成器函数
function * read() {
let data = yield readFile('./a.txt','utf8');
data = yield readFile(data,'utf8');
return data;
}
// 方法一:Generator
let it = read(); // 生成器函数返回一个 Iterator 迭代器对象
let {value:v1, done:d1} = it.next(); // 注意:第一个next传参是无效的
v1.then(data=>{
console.log(data) // b.txt
let {value:v2, done:d2} = it.next(data); // 将第一次的结果作为第二次的入参
return v2
}).then(data=>{
console.log(data) // 执行结果:c
})
// 方法二:使用 co 库
const co = require('co')
// co 方法:包装 generator 生成器函数,内部自动执行完成,返回一个 promise
co(read()).then(data=>{
console.log(data); // 执行结果:c
})
复制代码
对比 Generator 和 co 两种方案:
三,co 库的实现
手写一个 co 方法:主要使用了”异步迭代“的思想;
/**
* 自动执行迭代器
* @param {*} it generator执行返回的迭代器函数
* @returns
*/
function co(it) {
return new Promise((resolve, reject) => {
function next(data) { // 将上一次的结果作为下一次的入参
let { value, done } = it.next(data);
if (done) { // 迭代器执行完成,返回最终结果
resolve(value);
} else {
// 备注:使用 Promise.resolve 将 value 包装成Promise
// 成功:说明迭代器还没有执行完,继续递归调用 next,直至迭代器完成
Promise.resolve(value).then(next, reject);// 注意此处的 next 传入的是当前 function
}
}
next();// 第一次调用 next 时,传参是无效的
})
}
复制代码
四,结尾
本篇,主要介绍了 co 库的使用和实现原理,主要涉及以下几个点:
co 库的简介:特性、用法、功能分析;
co 库的实现和原理分析;
下一篇,继续介绍 async/await:generator 语法糖,嵌套回调问题的最终解决方案;
评论