我也来凑个热闹,看看编译后async/await
在koa 2里使用async
'use strict';
var http = require('http');
var koa = require('koa');
var app = new koa();
// number of middleware
var n = parseInt(process.env.MW || '1', 10);
console.log(' %s async middleware', n);
while (n--) {
app.use(async (ctx, next) => {
await next();
});
}
var body = new Buffer('Hello World');
app.use(async (ctx, next) => {
await next();
ctx.body = body;
});
// var apprequire('./koa2-async.js')
app.listen(3333);
module.exports = app
使用babel编译后,如下
'use strict';
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { return step("next", value); }, function (err) { return step("throw", err); }); } } return step("next"); }); }; }
var http = require('http');
var koa = require('koa');
var app = new koa();
// number of middleware
var n = parseInt(process.env.MW || '1', 10);
console.log(' %s async middleware', n);
while (n--) {
app.use((() => {
var ref = _asyncToGenerator(function* (ctx, next) {
yield next();
});
return function (_x, _x2) {
return ref.apply(this, arguments);
};
})());
}
var body = new Buffer('Hello World');
app.use((() => {
var ref = _asyncToGenerator(function* (ctx, next) {
yield next();
ctx.body = body;
});
return function (_x3, _x4) {
return ref.apply(this, arguments);
};
})());
// var apprequire('./koa2-async.js')
app.listen(3333);
module.exports = app;
看一下_asyncToGenerator函数,格式化后
function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch(error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(function(value) {
return step("next", value);
},
function(err) {
return step("throw", err);
});
}
}
return step("next");
});
};
}
很明显,把async函数通过高阶函数转为promise里嵌入的generator来执行的。
整体来说,随着中间件越多,它的性能越差,可以参见 koa、koa2、koa2-async和express的压测性能比较
再看await
app.use(async (ctx, next) => {
await next();
ctx.body = body;
});
翻译后
app.use((() => {
var ref = _asyncToGenerator(function* (ctx, next) {
yield next();
ctx.body = body;
});
return function (_x3, _x4) {
return ref.apply(this, arguments);
};
})());
很明显,await只是yield的别名
结论
- async/await不需要generator,自己带执行器
- 翻译后的await = yield
目前Thunk和Promise是一样,都可以接到yield后面,但await的native里的具体实现里还不好说。
另外据mikeal说,10月份可能会有async/await的native实现,拭目以待吧
如有不对的地方,请指正
你拿这破编译的有啥意思 自豪地采用 CNodeJS ionic
@captainblue2013 我不知道async/await还咋实现,请指教
v8实现的async/await ,个人猜测不会只是js层面的语法糖,应该会在底层做处理 From Noder
跟楼上一些观点一样,我也觉得 babel 的结果跟 V8 最终的实现不一定是一致的。babel 受限于目前 v8 的能力,无论用了 promise 还是 yield 都只能看做是一种对现实的妥协。
最终 async/await 的性能,以及与 generator 的差异,还是要看 v8 的实现。
Async/await should arrive – behind an ‘experimental’ flag – in Chrome 53, which is scheduled to be released into stable channel on 6 September, so will hopefully arrive (behind a flag) in Node v7, in October.
考虑到手机浏览器,这些都是渣渣,做过微信开发的都知道。
Q2 V8 会完成 async/await 的实现,Node 后面也会跟进吧,现在 babel 为了让大家体验新标准,做了很多 wrap 和 hack ,代码,速度上肯定是有损的。
等V8能解释async/await,这个编译器就不会编译async/await 了吧
举个例子,Chakra: 如果翻了Chakra的代码,就会发现yield和await在token解析时大多相邻甚至写在一起,最后到下面那个函数都以类型Js::OpCode::Yield进行处理。所以整块Chakra中,出现await的基本只有Parser部分。 (https://github.com/Microsoft/ChakraCore/blob/3254c38a313f4adfff87c887837ed870fd9e5023/lib/Runtime/ByteCode/ByteCodeEmitter.cpp#L11010)
(非专业,如有错误,敬请指出)
@zsxsoft 棒棒哒
本来就是语义层面的东西。。。为啥要下降到实现里讨论呢。。。先前yield编译还变成一堆switch呢,但是这有什么影响吗? await这种东西一看就明白了,yield看了之后还要考虑是不是有别的用法。除了常见的迭代器,之前我还用它做过一个有限状态机的核心部分,这种情况下yield就不能当作await用了。
来自酷炫的 CNodeMD
如果真要讲语义,是js吸收其他语言的东西有点饥不择食,yield和await选其一在语义上都没问题,但js吸收了两,这很自然就出现了各人喜好的问题。谁也没硬性规定yield不能干await的事情。同样对var和let,真需要用两个关键字来区分么?像lua这种本身就支持块级作用域的不用一个local就搞定了?
本质上,这是语言设计的问题。一门设计本身不完备,又处于利益场的中心,看似万千宠爱,其实身不由己,是个大公司都想加点自己的东西进去,以后真一年一个版本了,这个问题恐怕会更加突出。C++变得越来越复杂或许是因为情怀,js变得越来越让人无所适从则是因为赤裸裸的利益。
@coordcn C++复杂是因为情怀… js正在多元化的时候,不同的角度看来,它只能满足某些需求,也会因为需求的选择而最终趋于稳定。说赤裸裸的利益也没错,