【javascript】探究async与await原理

背景

  • 以前课上老师教这个语法的时候,会说async实际上就是promise的语法糖。后来又听某老师说async和await是generator+co的语法糖,这就让我迷糊了,于是自己探究下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函数。
  • 这个函数里面包了一个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来递归。
  • 关于这个和co的关系,下次整理下写出来。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值