LoginSignup
62
60

More than 5 years have passed since last update.

コールバック関数をPromise化して使う

Last updated at Posted at 2017-06-04

jsにおいてコールバック関数は頻出するパターンの一つである。
しかしながら、コールバックヘルという言葉があるとおりネストをすると非常に見づらくなっていく。

本記事では、Node環境においてindex.jsを読み込んで表示するスクリプトを例にいくつかのパターンを見ることにする。

index.js
'use strict';
const fs = require('fs');

fs.readFile('index.js', 'utf8', (err, out) => {
    if (err) {
        console.log(err);
    }
    console.log(out);
});

Promise化

node v8から導入されたutil.promisifyを使うとコールバックをpromise変換できる。

index.js
'use strict';
const {promisify} = require('util');
const fs = require('fs');

promisify(fs.readFile)('./index.js', 'utf-8').then(out => {
    console.log(out);
});

async/await

また、v8(ところでv8というとV8(実行エンジン)と区別がつかないことに気づいた)からはasync/awaitが使えるので以下のように書ける。

index.js
'use strict';
const { promisify } = require('util');
const fs = require('fs');

async function main()  {
    const out = await promisify(fs.readFile)('./index.js', 'utf-8');
    console.log(out);
}

main();

トップレベルawaitがほしいところではあるが、非同期処理が続くとコールバックより圧倒的に見やすいので積極的に使っていきたい。

pify

しかしながら、これらはv8からでないと使えないので多くの場合、ライブラリで代替することになるだろう。

promise化するライブラリの一つはpifyだ。

$ npm install --save pify

ほぼ、前述したpromisifyと同じように使える。
基本的に自分はこれを使っている。

sindresorhus/pify: Promisify a callback-style function

index.js
'use strict';
const fs = require('fs');
const pify = require('pify');

pify(fs.readFile)('./index.js', 'utf-8').then(out => {
    console.log(out);
});

非同期?

しかしながら、いつでも非同期が高速ではないことに注意すべきだ。

非同期処理にはオーバヘッドがあり、このようなイベントループをブロックことが問題ではない場合、同期的に書いたほうがはるかに高速に動作する。

index.js
'use strict';
const fs = require('fs');

const out = fs.readFileSync('./index.js', 'utf-8');
console.log(out);
62
60
2

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
62
60