async与await的原理揭秘
async和await是es7语法,在babel中会被转译,我们看一下专一前和转译后的源码:
async function p (){
await console.log('xx')
}
p()
async function w (){
console.log('xf')
}
转译后:
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function p() {
return _p.apply(this, arguments);
}
function _p() {
_p = _asyncToGenerator(function* () {
yield console.log("xx");
});
return _p.apply(this, arguments);
}
p();
function w() {
return _w.apply(this, arguments);
}
function _w() {
_w = _asyncToGenerator(function* () {
console.log("xf");
});
return _w.apply(this, arguments);
}
先解读下p函数,运行p函数就是运行_p函数,运行_p函数会返回里面的_asyncToGenerator函数。
_asyncToGenerator这个函数里面包了一个function*也就是生成器函数,通俗的说,就是将p函数给造成了function*函数。
再来仔细看下这个函数干了啥,这个函数返回一个函数,而这个返回的函数执行会返回一个传入的fn的返回值也就是那个生成器函数的返回值,这个生成器返回值第一次是这个生成器,第二次是它的yield语句,把返回结果做成gen,相当于
function * myfunc(){
yield console.log('myfunc')
}
gen = myfunc()
gen['next'](参数)//后面函数调用即可打印函数里yield语句
然后运行它里面定义的asyncGeneratorStep函数。
这个函数就比较简单了,注意上面例子的那段话,它就是用trycatch试着运行它的next,也就是function的yield,生成器函数会有done属性,如果完成了done就是true,如果没完,把返回值利用promise.resolve包裹起来递归。
再来看一下w函数,也就是没有加上await的在function*的生成器函数里就会以正常代码存在,如果有yield穿插,看在yield的什么位置,也就是看await的位置。
最后再梳理下整个过程,运行p函数>运行_p返回内部_p运行结果——也就是个递归Promise对象,这个对象会自动执行生成器yield,直到运行完。
async和await确实也算是Promise的语法糖,但实际是promise包裹了generator的语法糖。 源码中使用的特殊技巧: 这个Promise包裹的非常特别,是一个递归一直next直到没有yield才进行resolve的promise,如果下面还有yield,那么就调用Promise.resolve来递归。
相关文章
- 模型难复现不一定是作者的错,研究发现模型架构要背锅
- 一图配置Putty颜色
- easyswoole的核心文件
- 01-自动化工具的构建-天才老师防作弊
- STM32 RTC时钟
- 12张图看懂人工智能现状
- easyswoole的核心代码-看懂请求到返回流程
- 战争中的人脸识别:法国情报公司挖掘车臣士兵身份,乌克兰用来辨认战俘
- cocos cc.resource.loadDir在网页端正常安卓端报错的解决
- 关于人工智能消费趋势预测
- laravel + passport的Aouth2.0全解
- STM32 uC/OS-III移植
- 一眼能看出来是Auth::routes()是自动添加一批路由,那是怎么工作的呢?
- 突破184.3亿美元!人工智能领域再现“中国速度”
- 网络犯罪分子使用人工智能创建恶意软件攻击软件中的沙盒
- 观点:从七个方面看人工智能的失败
- 线程是来干嘛的
- swoole的官网怎么学习。彻底理清swoole架构
- 战争中的 AI :乌克兰用人脸识别「摸底」俄罗斯士兵,但这只是小儿科
- websocket的本质。 websocket一直返回200状态码、504码,搞了一下午。下次遇到知道就是后端的问题。