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

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

More than 3 years have passed since last update.

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);
akameco
シュレーディンガーの社会人.js
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