知识基础,了解generator的用法
// generator是实现async函数的关键
function* helloWorldGenerator() {
yield '1';
yield '2';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: '1', done: false }
hw.next()
// { value: '2', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
复制代码
案例
let fs = require('fs');
function readFile(filename) {
return new Promise(function (resolve, reject) {
fs.readFile(filename, function (err, data) {
if (err)
reject(err);
else
resolve(data);
})
})
}
function* read() {
let template = yield readFile('./template.txt');
let data = yield readFile('./data.txt');
return template + '+' + data;
}
co(read).then(function (data) {
console.log(data);
}, function (err) {
console.log(err);
});
复制代码
解析
这里需要注意的是co函数的实现(如下),co函数是用来模拟async的关键
function co(gen) {
// 初始化迭代器
let it = gen();
return new Promise(function (resolve, reject) {
// 递归调用next,确保yeild后面的内容依次全部执行
!function next(lastVal) {
let {value, done} = it.next(lastVal);
if (done) {
resolve(value);
} else {
// 每次yield 的值,会作为next函数的参数
// 所以上面的例子 let template = yield readFile('./template.txt') ,template就是yeild表达式返回的值
value.then(next, reason => reject(reason));
}
}();
});
}
复制代码
补充
// async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。
async function read() {
let template = await readFile('./template.txt');
let data = await readFile('./data.txt');
return template + '+' + data;
}
// 等同于
function read(){
return co(function*() {
let template = yield readFile('./template.txt');
let data = yield readFile('./data.txt');
return template + '+' + data;
});
}
复制代码