function foo(x,y) {
return new Promise(function(resolve, reject) {
ajax("http://some.url.1/?x=" + x + "&y=" + y, function(data){
resolve(data);
});
})
}
function *main() {
try {
var text = yield foo( 11, 31 );
console.log( text );
}
catch (err) {
console.error( err );
}
}
var it = main();
var p = it.next().value;
p.then(
function(text){
it.next( text );
},
function(err){
it.throw( err );
}
);
我的github博客 https://github.com/zhuanyongxigua/blog
ES6之前,JS的函数只能一口气执行到底,Generator的出现使得JS的函数可以做到停顿,根据需要一步步执行。如果没有Generator,可以用闭包来模拟,可这种实现并不方便。
关于generator的运行机制,可以将它简单的总结为三点,详细信息见mdn:
对于Generator的应用场景,最合适的应当就是对异步嵌套的优化了。
一段来自《YDKJS》很精彩的代码:
在调用了next方法之后,请求发出,在请求的回调函数里面
return
没有意义,拿不到返回值,所以在回调里面再调用一次next方法,并把返回的数据当做参数传入。非常巧妙的运用了Generator的特性。Generator对异步写法的优化非常优秀,比Promise更好,但promise解决的不光是可读性的问题,还有信任问题。
所以,我们需要用Generator + promise的模式。
基本版:
这个基础的版本,如果main函数里面有多个步骤,每次调用next方法之后,还要再手写一个Promise链,可以自己封装一个runner方法,一口气把Generator执行到底。
总结一下Generator:它对异步可读性的优化比Promise更好,可有了async/await之后,我也不知道generator还有什么用了(对于模拟多线程之类的应用,我想象不出会有大量应用的场景)。Generator更像是一个过渡性的工具。
async/await
从Generator的思路过来,async/await的方式更像是对Generator的进一步简化。async/await的写法,不需要封装runner也可以执行到底。
此外需要注意的是要正确使用await,没有相互依赖关系的异步操作,不要在同一个async函数里面用await,具体参考How to escape async/await hell
参考资料: