Node.js asyncの有効な使い方




シンプルなasync

ES7のasync/awaitではありません。2017年にもなってnpmのasyncの記事かよと思う方もいますが、4年間ほどソーシャルゲームの大規模開発で学んだasyncの使い方をまとめておきたいと思います。

まず簡単にasyncのメリットとデメリットを紹介しておきます。

メリット

  1. シンプルなAPI
  2. 並列処理と逐次処理を同じインターフェースで記述できる

デメリット

  1. 記述量が多くなる
  2. 並列処理のエラーハンドリング怪しい
  3. 今後ベースとなるPromise互換ではない

デメリットとして今後Node.jsではPromiseが主流になるのは確実なのでasyncはもう使われなくなることですね。けど、小さい処理のプログラムは今でも自分はasyncを使ってます。

asyncサンプルコード

逐次処理 waterfall

  • waterfall

waterfallの第一引数に関数を詰めた配列を渡すだけです。逐次処理は基本これで問題ないです。

async.waterfall([
    function(callback) {
        userDao.getByUserName('superman', callback);
    },
    function(user, callback) {
        userItemDao.getByUserId(user.id, callback);
    }
], function(error, userItem) {
    if (error) {
        console.log(error);
        return;
    }
    console.log('userItem' + userItemp)
});

並列処理 parallel

  • parallel
async.parallel({
    user: function(callback) {
        userDao.getByUserName('superman', callback);
    },
    item: function(callback) {
        userItemDao.getByName('item1', callback);
    }
}, function(error, result) {
    if (error) {
        console.log(error);
        return;
    }
    console.log('result' + result);
    // {user: {id: 1, name: ...}, item: {id:1, name: ...}}
});

繰り返し処理 each, forEachOf

  • each(eachSeries)

eachは並列処理になるのでuserListの中は順不同になります。eachSeriesは配列の最初の要素から順番に処理されるので、一個ずつ処理した場合はeachSeriesを使いましょう。インターフェーは変わらないのでeachをeachSeriesに変更するだけで大丈夫です。

var userList = [];
var userIdList = [1, 2, 3, 4];
async.each(userIdList, function(userId, callback) {
    userDao.getById(userId, function(error, user) {
        if (error) {
            callback(error);
            return;
        }
        console.log(user);
        userList.push(user);  
        callback();
    });
}, function(error) {
    if (error) {
        console.log(error);
        return;
    }
    console.log('userList: ' + userList);
    // 配列内は順不同になる[user1, user2, user3, user4]
});

 

  • forEachOf(forEachOfSeries)

これはObjectを回すときに使用します。eachと同様、1個ずつ処理したい場合はforEachOfSeriesに変更するだけで大丈夫です。

var userIdMap = {userId1: 1, userId2: 2, userId3: 3, userId4: 4};
async.forEachOf(userIdMap, function(value, key, userId, callback) {
    userDao.getById(value, function(error, user) {
        if (error) {
            callback(error);
            return;
        }
        console.log(user);
        callback();
    });
}, function(error) {
    if (error) {
        console.log(error);
        return;
    }
});

まとめ

シンプルで使い方の簡単なasyncはどうでしたか?今後のメインストリームではなくなりますが、使い方が簡単なのでちょっとした処理で試してみてください。

おすすめ書籍

基礎から応用までサンプルコードを使って解説しており、Node.jsが初めての人でも読める技術書となっています。上級者向けにはExpressフレームワークを使った実用的な開発手法の解説もありこれからアプリケーションを開発する人の参考になると思います。現状では書き方が古くなっていますが、Node.jsの初心者から上級者で学ぶことの多い書籍です。

 

The following two tabs change content below.

髙妻智一

2013年CyberAgent新卒入社 スマホゲームを作る子会社に所属し、サーバーサイドのエンジニアを担当。2年目の終わりから新規子会社の立ち上げに参加し、サーバーサイドのエンジニアリーダーとしてサービースのリリースから運用までを担当。 2018年仮想通貨のスマホウォレットを提供するGinco Incにブロックチェーンエンジニアとして入社。






よく読まれている関連記事はこちら



コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です