at backyard

Color my life with the chaos of trouble.

Node.js v 0.10系で、Promiseなどを使わないで、無理矢理に同期処理を行う。

JavaScript備忘録記事。

今年に入ってからNode.js + MongoDB(with mongoose)という組み合わせで仕事をしている。
ただ、プロジェクトの諸事情により、最近までNode.jsはPromiseが使えない古いバージョンを使わざる負えない状況だった。
具体的には0.10系。
そうなると困るのが同期的な処理をしたい時。

例えば"mongoose"を使って、指定した値を取得し処理をしたい時などに困るシーンが出てくる。
具体的には下記のような泥臭い処理を実装して凌いでいた。

var userModel = dataModel.getUserModel(); // "user"コレクションのMpdel取処理とする

// userコレクションから"country"が"us"のデータを取得する
userModel.find({"country" : "us"}, function(err, users) {

  // エラー処理
  if(err) {
    errorHandling();
  }

  // 取得件数が0件の場合の処理
  if(users.length === 0) {
    notGetProcessing();
  }

  // global変数として持たせることで共通的なカウンターとして使用
  counter = users.length;
  console.log("find user count : ", counter;

  users.forEach(function(user) {
    // 取得したデータに対する処理。この場合、"Processing"に処理を移し、
	// そちらでの処理が完了した後にGlobal変数である"counter"を-1していく
    setTimeout(function(a) {
      processing(a);
    },1000, user);
  });

  // Global変数である"counter"が"0"になった時点で、
  // 取得データに対する処理が全て完了したものとし、終了関数に処理を渡す
  setInterval(function() {
    if(counter === 0) {
      // End processing
      endProcess();
    }
  }, 100);
});

相当なスパゲティコードである。茹ですぎて完全に伸びている状態といったところか。
このように泥臭い処理をいたるところでしていたので、
相当コードがスパゲティになっていて、保守コストも高く付きそうになってしまっていた。
が、ある時点でNodeのバージョンが上がることになり、今ではバージョン6系で書いている。

Promiseも使えるようになったので、おかげで下記のように処理を変更できる。
(青臭いコードかもしれない。もし、もっとこうした方がスマートに出来るなどありましたら、コメントいただけると幸いです。。。)

// "country"が"us"のuserデータをPromiseで取得
function getUsUser() {
  let userModel = dataModel.getUserModel();
  return userModel.find({"country" : "us"}).exec();
}

// メイン処理
function main() {
  let promise = getUsUser();
  promise.then(function(users) {

    // 取得件数が0件の場合の処理
    if(users.length === 0) {
      notGetProcessing();
    }

    console.log("find user count: ", users.length);

    // 取得した全データに対して処理を行う
    users.forEach(function(user) {
      processing(user);
    });

    return users.length;
  })
  .then(function(userCount) {
    console.log("Successful user count : ", userCount);

    // 終了処理
    endProcess();
  })
  .catch(function(err) {
    conosole.log(err);

    // 終了処理
    endProcess();
  });
}

// 実行関数
main();

毎日泥臭いコードを書いていたのは大変だったが、
いかにして無理やり同期的に処理させるか?と考えてコードをガリガリ書いていたのは、
それはそれでとても勉強になったと感じている。