Generator 函数 是一种懒函数,相比普通函数而言,前面多个 *,但是使用起来大不同。
const foo = function * () {
yield "foo";
};
const generator = foo();
let result = generator.next();
console.log(result);
首先先创建generator 实例,然后调用next 方法,让函数进行运行。会返回当前yield后的值 和 generator实例状态。
当我们通过next 传值时,会将值赋给 上个yield 的结果并且返回下一个yield后的值。
const foo = function * () {
let result = yield "foo";
console.log(result, "yield");
};
const generator = foo();
let result = generator.next();
generator.next("bar");
通过generator.throw() 方法主动抛出异常
const foo = function * () {
try {
let result = yield "foo";
console.log(result, "yield");
} catch (error) {
console.log(error);
}
};
const generator = foo();
let result = generator.next();
generator.throw(new Error("ddd"));
function ajax(url) {
return new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open('GET',url);
xhr.responseType = 'json';
xhr.onload = function() {
if(this.status == 200) {
resolve(this.response);
} else {
reject(this.statusText);
}
}
xhr.send();
})
}
const foo = function * () {
let result1 = yield ajax("/api/book.json");
console.log(result1);
let result2 = yield ajax("/api/user.json");
console.log(result2);
};
const generator = foo();
generator.next().value.then(result =>{
return generator.next(result).value
}).then(result =>{
return generator.next(result).value
})
上边方法有个局现性,要手写各种情况,不智能啊,可以用递归解决
const foo = function * () {
try {
let result1 = yield ajax("/api/book.json");
console.log(result1);
let result2 = yield ajax("/api/user.json");
console.log(result2);
} catch (error) {
console.log(error);
}
};
function co(generatorFun) {
const g = generatorFun();
function handleResult(result){
// 生成器函数结束
if(result.done) return;
result.value.then(data =>{
handleResult(g.next(data));
}, err => {
g.throw(new Error(err));
})
}
handleResult(g.next());
}
co(foo);
async/await 本质上是Generator的语法糖,内部帮我们封装了生成器函数,比如上面的例子改写
const foo = async function() {
try {
let result1 = await ajax("/api/book.json");
console.log(result1);
let result2 = await ajax("/api/user.json");
console.log(result2);
} catch (error) {
console.log(error);
}
};
foo().then(result=> {
console.log("全部执行完成");
});