145
139

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ES7 の Async/Await を使ってみた

Last updated at Posted at 2015-03-11

Taming the asynchronous beast with ES7

babel の experimental に ES7 の Async/Await が入ったというので、さっそく導入してみた。対象は画像を点字を変換するわりかしどうでも良いモジュール。

導入前

ファイル読み込みや画像の変換に非同期処理を多用しており、node.js スタイルの 非同期API(コールバックを渡すやつ) を prominence というユーティリティ関数で Promise 化していたが、行ごとに then が出てきたり、複数の値を渡すために Promise.all を使ったりと、あまり読みやすいとは言えないコードだった。(コールバック地獄になるよりはマシだと思うけど..)

convert.js
import gm from "gm";
import pngparse from "pngparse";

// 画像を点字に変換する
let convert = (src, opts) => {
  // 画像を GraphicsMagick の形式に変換
  return Promise.resolve(gm(src)).then((im) => {
    // サイズを取得
    return Promise.all([ im, prominence(im).size() ]);
  }).then(([ im, size ]) => {
    // 画像を加工 (省略)
    return im;
  }).then((im) => {
    // PNGに変換
    return prominence(im).toBuffer("png");
  }).then((buffer) => {
    // PNGをパース
    return prominence(pngparse).parse(buffer);
  }).then((png) => {
    // PNGを点字に変換 (省略)
    return "点字";
  });
};

導入準備

まず babel をアップデートして、devDependencies から dependencies に移動。

package.json
"dependencies": {
    "babel": "^4.7.8"
}

.babelrc で ES7 機能を使うフラグを設定。

.babelrc
{
  "experimental": true
}

async/await を使うファイルで babel/polyfill をインポートする。これがないと実行時に "regeneratorRuntime is not defined" というエラーが出る。

import "babel/polyfill";

導入後

await を使う関数自体を async function にして、非同期処理を行う関数呼び出しに await を追加するだけ。手続き型言語!!という感じで、コードの見通しは非常に良くなったと思う。使う側のコードに変更は不要で、書き換える前と同じインターフェース(この場合はPromise)で使える。

convert.js
import gm from "gm";
import pngparse from "pngparse";

// 画像を点字に変換する
export async function convert(src, opts) {
  // 画像を GraphicsMagick の形式に変換
  let im = gm(src);

  // サイズを取得
  let size = await prominence(im).size();

  // 画像を加工 (省略)

  // PNGに変換
  let buffer = await prominence(im).toBuffer("png");

  // PNGをパース
  let png = await prominence(pngparse).parse(buffer);

  // PNGを点字に変換 (省略)
  return "点字";
};

知見

事前にPromise化していた効果が大きかったのか、コードの書き換えはあっという間にできた。最近 Promise がいまいち使いづらいと思い始めていたけど、使い続けるモチベーションにはなった。

失ったもの

  • lint (jshint) が使えなくなったので消した

diff

145
139
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
145
139

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?