一、生成器函数基本用法
Generator 函数调用和普通函数不同,它会返回一个迭代器,允许程序在函数内部定义一系列可暂停执行的点,并在需要的时候恢复执行。Generator 函数通过
function*关键字来声明,并在其内部使用yield表达式来标识这些暂停点。每次调用next()方法时,Generator 函数会从上次离开的位置恢复执行直到遇到下一个yield表达式,此时它会返回一个包含{ value: ..., done: ... }结构的对象,其中value是yield表达式后面表达式的值,done标记着 Generator 函数是否已经完全执行完毕。
以下是一个简单的 Generator 函数示例:
function* foo(x) {
let y = 2 * (yield (x + 1))
let z = yield (y / 3)
return (x + y + z)
}
let it = foo(5);
console.log(it.next()); // {value: 6, done: false}
console.log(it.next(12)); // {value: 8, done: false}
console.log(it.next(13)); // {value: 42, done: true}
二、实现一个简单的async、await功能
通过asyncToGenerator函数对myGenerator函数进行处理,使其可以像async、await一样来进行使用。
function asyncToGenerator (generatorFunc) {
return function () {
const generator = generatorFunc.apply(this, arguments);
return new Promise((resolve, reject) => {
function step (key, arg) {
let generatorResult;
try {
generatorResult = generator[key](arg);
}
catch (error) {
return reject(error);
}
const { value, done } = generatorResult;
if (done) {
return resolve(value);
}
else {
return Promise.resolve(value).then(
val => step("next", val),
err => step("throw", err)
);
}
}
return step("next");
});
};
}
// 写法和async和await相同
function* myGenerator () {
try {
// result 即为resolve抛出数据
const result = yield new Promise(resolve => {
// 异步事件,例:ajax,通过resolve抛出
resolve("fqwikhfkjqw");
});
// console.log(result); // ===> fqwikhfkjqw
// 返回值和async函数返回值作用相同
return "ffffffff";
}
catch (error) {
throw new Error(error);
}
}
// 测试使用
let asyncFunc = asyncToGenerator(myGenerator);
asyncFunc();