Generator的理解
1. 跟普通函数一样,就是在声明function前面多了一个 *
2. 是一个生成器函数:调用一个生成器函数不会立即执行,返回一个生成器对象
- 调用它的next()方法来返回值,可以随时yield关键词,向外返回值,通过next()方法来拿到这个值
- 返回值有一个done属性,用来表示当前的生成器函数是否执行完毕
- yield暂停生成器函数的执行,直到调用next()方法才会继续向下执行
- next()方法中传一个值,将作为yield的返回值
- 调用生成器函数的throw方法,会抛异常
function * foo() {
try {
console.log('generator start!');
let f1 = yield 'foo'; // yield会暂停函数执行,直到调用next()方法,向下执行
console.log(f1); // 123
} catch (error) {
console.log(e);
}
}
let generator = foo(); // 调用foo()没有立即执行这个函数,只是得到一个生成器对象,第一次调用next()的方法,这个函数体才会执行
generator.next(); // 调用next方法,输出 generator start!
generator.next(123); // 传入的值为yield的返回值
generator.throw(new Error('Generator Error')); // 抛出异常,会在catch中捕获异常
Generator异步方案
- 普通的实现
function * main() {
try {
const user = yield ajax('./api/users.json');
console.log('user', user);
const post = yield ajax('./api/posts.json');
console.log('post', user);
const foo = yield ajax('./api/foo.json');
console.log('foo', foo);
} catch (error) {
console.log('error', error);
}
}
const g = main(); // 调用不会立即执行,返回一个生成器对象
const result1 = g.next();
if (result1.done) return;
result1.value.then(data => {
const result2 = g.next(data);
if (result2.done) return;
result2.value.then(data => {
const result3 = g.next(data);
if (result3.done) return;
})
})
- 使用递归实现一个生成器函数的一个执行器
function handleResult(result) {
if(result.done) return;
result.value.then(data => {
handleResult(g.next(data))
}).catch(err => {
g.throw(new Error(err));
})
}
handleResult(g.next());
- 封装一个生成器函数,传一个generator作为参数,更加实用,代码复用
function co(generator) {
const g = generator();
function handleResult(result) {
if(result.done) return;
result.value.then(data => {
handleResult(g.next(data))
}).catch(err => {
g.throw(new Error(err));
})
}
handleResult(g.next());
}
co(main);
其实es7的 async/await 就是 Generator + co 自动执行器函数 实现的,async声明函数返回一个Promise对象,遇到await等待await后面的程序执行完毕才会接着执行下面的同步代码