LoginSignup
263

More than 5 years have passed since last update.

Node.jsの人はちゃんとsleepしてください

Last updated at Posted at 2014-05-28

Node.jsでがんばりすぎると別のプロセスに迷惑だから長いことかかる処理は sleep() みたいなのを挟みながらやりたいなー。

と思ってググった結果がこうですよ。

  binding = {
    sleep: function(s) {
      var e = new Date().getTime() + (s * 1000);

      while (new Date().getTime() <= e) {
        /* do nothing, but burn a lot of CPU while doing so */
        /* jshint noempty: false */
      }
    },

だめですね。これCPU使いまくり。

まあ、CPUがいくら発熱してもいいよって思っても、制御が別のタスクに行かないのはアウトです。たとえばこれがサーバのリクエストハンドラに使われてたら、みんな一定秒数遅れてページ表示される、んじゃなくて、 サーバーが一定秒数止まる ことになる。つまり、そのリクエストに3人来たら、3人目は1人目の3倍待たないといけない。

もしコールバック連鎖を使ってるバックグラウンドスレッド(DBのバッチ更新トランザクションとか)があった場合は、sleep してメイン処理を待機させようとしたつもりが、肝心のバックグラウンド処理を止めてしまうことに。

CPUを使いすぎることはREADMEにちゃんと書いてあるんですが、マルチタスクが止まるって点には言及してない。

On windows the module will fall back to a while loop which will use 100% CPU!

まーね、これはネタリポジトリだろうしね...

https://www.npmjs.org/package/sleep

186 downloads in the last day
1001 downloads in the last week
4741 downloads in the last month

え、いいのかきみたち! コレジャナイってなるよ。

だいたい誰がこんな...

Nodeビギナーズブック » Node.jsチュートリアル » Node.js 教程 #ブロッキングとノンブロッキング

おまえかー!! まったくもー、「悪い例」ってちゃんと書いといてよ。

というわけで、綺麗なスリープはこう書くといいよというのを、async.js 使って説明します。

var async = require('async');

var repeating = 0;
async.forever(function(callback) {
    async.series([
        function(callback) {
            console.log("どっこらせー");
            setTimeout(callback, 1000);
        },
        function(callback) {
            console.log("よっこいせー");
            setTimeout(callback, 1000);
        },
        function(callback) {
            if (++repeating < 5) {
                callback();
            } else {
                console.log("おしまい");
            }
        }
    ], callback);
}, function(err) {
    console.log(err);
});

setTimeout() のコールバックが async の次のステップに行くトリガーになるのがポイント。

ちなみにコールバック地獄版はこちら。

var repeating = 0;
(function() {
    var redoFunc = arguments.callee;
    console.log("どっこらせー");
    setTimeout(function(){
        console.log("よっこいせー");
        setTimeout(function() {
            if (++repeating >= 5) {
                console.log('おしまい');
            } else {
                redoFunc();
            }
        }, 1000);
    }, 1000);
})();

上級者はもっといい方法を知ってるのかなぁ。

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
263