Help us understand the problem. What is going on with this article?

Babelのasync/await試してみた(+中の処理をちょっと追ってみた)

More than 5 years have passed since last update.

npm install babel -g

experimentalオプション必須なので コンパイルは babel -e foo.es6 > foo.js みたいな感じ

適当に試してみた。

import "babel/polyfill";

let wait = function(n: number){
  return new Promise(done => setTimeout(() => done(n), n));
};

let main = async function(){
  await wait(50);
  console.log('await done');
}

// async promise nomally
wait(100).then(() => console.log('promise normaly done'));

// await
main();

最初awaitブロックがasyncを取るのが必須なことに気づかなくて、普通に呼ぼうとしてちょっとハマった。まあ処理系やポリフィルの都合そうなるのはなんとなくわかる。

これasync () => {...}await () => {...}みたいな Arrow Functionでも動くのかなぁと思って次のコード試してみた。

import "babel/polyfill";
(async () => {
  await new Promise(done => setTimeout(() => {console.log('done 1'); done()}, 100));
  await new Promise(done => setTimeout(() => {console.log('done 2'); done()}, 100));
})()

じゃあワンライナーもいけるじゃんと試してみたら動いた

import "babel/polyfill";
(async () => await new Promise(done => setTimeout(() => {console.log('wait done'); done()}, 1000)))()

吐かれたコード読んでみる。

"use strict";

var _this = this;

require("babel/polyfill");

(function callee$0$0() {
  return regeneratorRuntime.async(function callee$0$0$(context$1$0) {
    while (1) switch (context$1$0.prev = context$1$0.next) {
      case 0:
        context$1$0.next = 2;
        return new Promise(function (done) {
          return setTimeout(function () {
            console.log("wait done");done();
          }, 1000);
        });

      case 2:
        return context$1$0.abrupt("return", context$1$0.sent);

      case 3:
      case "end":
        return context$1$0.stop();
    }
  }, null, _this);
})();

あんまり読みたくはないのが出てきたが… とりあえず追っていったところ https://github.com/babel/regenerator-babel/blob/master/runtime.js を使っている。

https://github.com/babel/regenerator-babel/blob/master/runtime.js#L96-L119 をみたところGeneratorってのでwrapしてPromiseをキューにしてさばき終えるのを待ってて、割と素直だった。というかAST読んでからの式変形の実装が強そう。(これCPS変換って言っていいんだろうか)

babel/polyfillがcommonjs requireのままなのでブラウザに持ってくにはbrowserify前提な感じ。

式からawaitの出現数を数えてcase作ってるようにみえたので、forで回すちょっと意地悪なコード書いてみる。

import "babel/polyfill";
(async () => {
 for(var i = 0; i < 10; i++){
   await new Promise(done => setTimeout(() => {console.log('wait done'); done()}, 100));
 }
})();

ちゃんと動いた。が、出力みて頭かしげた。

"use strict";

var _this = this;

require("babel/polyfill");

(function callee$0$0() {
  var i;
  return regeneratorRuntime.async(function callee$0$0$(context$1$0) {
    while (1) switch (context$1$0.prev = context$1$0.next) {
      case 0:
        i = 0;

      case 1:
        if (!(i < 10)) {
          context$1$0.next = 7;
          break;
        }

        context$1$0.next = 4;
        return new Promise(function (done) {
          return setTimeout(function () {
            console.log("wait done");done();
          }, 100);
        });

      case 4:
        i++;
        context$1$0.next = 1;
        break;

      case 7:
      case "end":
        return context$1$0.stop();
    }
  }, null, _this);
})();

これ、いわゆるswitchによるgoto… なんかllvmがCから出力したIRみたいだ。

なんか納得感あったのでこれで終わり。

plaid
CXプラットフォーム「KARTE」の開発・運営、EC特化型メディア「Shopping Tribe」の企画・運営、CX特化型メディア「XD(クロスディー)」の企画・運営
https://plaid.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした