异步函数

异步函数
在 4.2 节中,我们提到了一个关于直接在语法上支持这个模式的提案:生成器向类似运行
器的工具 yield 出 promise,这个运行器工具会在 promise 完成时恢复生成器。让我们来简
单了解一下这个提案提出的特性 async function。
回忆一下第 4 章里这个生成器的例子:
run( function *main() {
var ret = yield step1();
try {
ret = yield step2( ret );
}
catch (err) {
ret = yield step2Failed( err );
}
ret = yield Promise.all([
step3a( ret ),
step3b( ret ),
step3c( ret )
]);
yield step4( ret );
} )
.then(
function fulfilled(){
// *main()成功完成
},
function rejected(reason){
// 哎呀,出错了
}
);
提案的 async function 语法不需要 run(…) 工具就可以表达同样的流控制逻辑,因为
JavaScript 将会自动了解如何寻找要等待和恢复的 promise。
考虑:
async function main() {
var ret = await step1();
try {
ret = await step2( ret );
}
catch (err) {
ret = await step2Failed( err );
}
ret = await Promise.all( [
图灵社区会员 avilang(1985945885@qq.com) 专享 尊重版权
ES6 之后 | 255
step3a( ret ),
step3b( ret ),
step3c( ret )
] );
await step4( ret );
}
main()
.then(
function fulfilled(){
// main()成功完成
},
function rejected(reason){
// 哎呀,出错了
}
);
我们没有使用 function main() {… 声明,而是使用了 async function main() {… 形式。
而且,没有 yield 出一个 promise,而是 await 这个 promise。调用来运行函数 main() 实际
上返回了一个可以直接观察的 promise。这和从 run(main) 调用返回的 promise 是等价的。
看到这种对称性了吗? async function 本质上就是生成器+ promise + run(…) 模式的语
法糖;它们底层的运作方式是一样的!
如果你是一个 C# 开发者,那么一定很熟悉这个 async/await 模式,因为这个特性就是直接
来自于 C# 的对应特性。很高兴看到语言特性收敛。
Babel、Traceur 和其他 transpiler 都已经对当前状态的 async function 提供了早期支持,
所以已经可以开始使用这个特性了。但在下一小节中,我们将会介绍为什么现在有点为
时尚早。
还有一个对 async function
的提案,可以称之为“异步生成器”。你可
以在同一段代码中既 yield 又 await,甚至可以把这两个运算放在同一个
语句:x = await yield y。这个“异步生成器”提案似乎更不稳定——
具体说,它的返回值还没有完全确定。有些人认为返回值应该是一个
observable,有点类似于一个迭代器和一个 promise 的合并。目前我们不会
深入探讨这个主题,但会对它保持关注。
警告
async function 有一个没有解决的问题,因为它只返回一个 promise,所以没有办法从外部
取消一个正在运行的 async function 实例。如果这个异步操作的资源紧张,那么可能会引
起问题,因为一旦你确认不需要结果就会想要释放资源。
图灵社区会员 avilang(1985945885@qq.com) 专享 尊重版权
256 | 第 8 章
举例来说:
async function request(url) {
var resp = await (
new Promise( function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open( “GET”, url );
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve( xhr );
}
else {
reject( xhr.statusText );
}
}
};
xhr.send();
} )
);
return resp.responseText;
}
var pr = request( “http://some.url.1” );
pr.then(
function fulfilled(responseText){
// ajax成功
},
function rejected(reason){
//哎呀,出错了
}
);
我给出的这个 request(…) 有点像最近提出要集成到 Web 平台上的 fetch(…) 工具。那么问
题来了,如果你想要用 pr 值以某种方法指示取消一个长时间运行的 Ajax 请求会怎样呢?
Promise 是不可取消的(至少在编写本部分的时候是如此)。和很多人一样,我的看法是
它们永远不应该被取消(参见本系列《你不知道的 JavaScript(中卷)》第二部分)。而且
即使它有一个 cancel() 方法,就一定意味着调用 pr.cancel() 应该把取消信号一路沿着
promise 链传播回到 async function 吗?
这个争论有以下几个可能的解决方案:
• async function 根本不能被取消(现状);
• 可以在调用异步函数的时候传入一个“取消令牌”;
• 返回值变成一个新增的可取消 promise 类型;
• 返回值变成某种非 promise 的东西(比如,observable,或者支持 promise 和取消功能的
控制令牌)。
图灵社区会员 avilang(1985945885@qq.com) 专享 尊重版权
ES6 之后 | 257
编写本部分时,async function 返回普通 promise,所以返回值不太可能会彻底改变。但是
判断最终如何发展还为时过早。我们对这个讨论保持关注吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值