async是es6提出的一种新的异步语法. 一开始es为了解决异步,使用的是promise, 但看到满屏的then之后,就感觉自己傻逼了. 后来提出了generator, 在底层实现了一个异步的模式, 但需要手动执行. 关于如何使用generator,可以参考,. 本文这里,不探讨怎么使用generato. 而是,如果使用generator和promise 构造出async的表达.
简单异步实现
一般异步的写法就是,传回调嘛,比如:
var ajax = function(url,cb){ // send url // get res ... cb(JSON.parse(result))}
这样,应该最容易写成callback hell. 然后我们引入: generator
function *main() { var result1 = yield ajax( "http://some.url.1" ); var data = JSON.parse( result1 ); var result2 = yield ajax( "http://some.url.2?id=" + data.id ); var resp = JSON.parse( result2 );}var async = main();async.next();function ajax(url){ // send url async.next(res);}
伪代码的格式如上所述. 这里,需要主意一个点. 如果,你没有在next()中传入res,like async.next()
. 那么,里面result1和result2获得的结果就是undefined.
async why?
根据上面的解析,我们可以了解到, 使用next 执行语句时, 只能执行yield后面的表达式. 这样造成的结果就是,不能parallel异步呀. 这样限制性还是很大的。所以,为了解决这个问题,使用到es6提出的Promise对象来进行补充.
这里,增加一个限定规则,即,ajax拉取返回的必须是一个promise对象.function ajax(url){ return new Promise(function(res,rej){ send(url,function(result){ res(result) }) })}
我们再补充一下,如果使用generator来对promise进行tricky
function runGenerator(g) { var it = g(), ret; (function iterate(val){ ret = it.next( val ); if (!ret.done) { // 检查是否已经then完成 if ("then" in ret.value) { // 这一句很关键 ret.value.then( iterate ); } else { // 同步回调的trick setTimeout( function(){ iterate( ret.value ); }, 0 ); } } })();}
OK, 这样, 我们就可以在async里面,使用同步的写法,来代表异步的操作了.
runGenerator(function* (){ var result = yield new Promise(function(res,rej){ setTimeout(function(){ res('ok'); },1000) });})
由于这里要求的是使用promise, 那么,我们使用Promise.all([xx,xx]) 也是合情合理的. 这样就可以完美的解决掉--并行异步发送。
runGenerator(function* (){ yield Promise.all([ajax('http://villainhr.com'),ajax('http://villainhr.com')])})
对比与,使用async的结构:
(async function(){ await Promise.all([ajax('http://villainhr.com'),ajax('http://villainhr.com')]);})();
是不是感觉一毛一样呢? 不过在实际上操作中, async 还必须对new Promise进行兼容处理. 如果其他人直接传入一个expression, 你也必须保证他是可行的.
在babel中,讲的其实也是这样一个逻辑:// Inasync function foo() { await bar();}// Outvar _asyncToGenerator = function (fn) { ...};var foo = _asyncToGenerator(function* () { yield bar();});
具体参考: