21

それで、私は頭の体操について考えていました - 何らかの理由でノード js で反復する必要がある大きなオブジェクトがあり、それを行っている間、イベント ループをブロックしたくない場合はどうすればよいでしょうか?

これは私の頭の一番上にある例です。私はそれがはるかにきれいになると確信しています:

var forin = function(obj,callback){
    var keys = Object.keys(obj),
        index = 0,
        interval = setInterval(function(){
            if(index < keys.length){
                callback(keys[index],obj[keys[index]],obj);
            } else {
                clearInterval(interval);
            }
            index ++;
        },0);
}

乱雑になる他の理由があると確信していますが、 setInterval 0 は実際には 0 ミリ秒ごとに実行されるわけではないため、これは通常の for ループよりも遅く実行されますが、多くのループを作成する方法がわかりませんより高速な process.nextTick。

私のテストでは、ネイティブの for ループ (hasOwnProperty() チェックを使用して同じ情報をログに記録) では 4 ミリ秒かかるのに対し、この例の実行には 7 ミリ秒かかることがわかりました。

では、node.js を使用してこの同じコードを記述する最もクリーンで最速の方法は何ですか?

4

4 に答える 4

2

ここで言うべきことがたくさんあります。

  • たとえば、Webアプリケーションがある場合、そのアプリケーションのプロセスで「重労働」を実行したくないでしょう。アルゴリズムは効率的ですが、それでもおそらくアプリの速度が低下します。
  • 達成しようとしていることに応じて、おそらく次のいずれかのアプローチを使用します。a

    )「forin」ループを子プロセスに配置し、終了したらメインアプリで結果を取得します
    。b)試行している場合遅延ジョブ(メールの送信など)のようなものを実現するには、 https://github.com/LearnBoost/kue
    を試してください 。c)Redisを使用して独自のKueのようなプログラムを作成し、メインアプリと「重労働」の間で通信します。 " アプリ。

これらのアプローチでは、複数のプロセスを使用することもできます(並行性のため)。

今度はサンプルコードの時間です(完璧ではないかもしれないので、もっと良い提案があれば私を訂正してください):

var forIn, obj;

// the "for in" loop
forIn = function(obj, callback){
  var keys = Object.keys(obj);
  (function iterate(keys) {
    process.nextTick(function () {
      callback(keys[0], obj[keys[0]]);
      return ((keys = keys.slice(1)).length && iterate(keys));
    });
  })(keys);
};

// example usage of forIn
// console.log the key-val pair in the callback
function start_processing_the_big_object(my_object) {
  forIn(my_object, function (key, val) { console.log("key: %s; val: %s;", key, val); });
}

// Let's simulate a big object here
// and call the function above once the object is created
obj = {};
(function test(obj, i) {
  obj[i--] = "blah_blah_" + i;
  if (!i) { start_processing_the_big_object(obj); }
  return (i && process.nextTick(function() { test(obj, i); }));
})(obj, 30000);
于 2011-11-03T22:39:39.357 に答える
1

それ以外の:

for (var i=0; i<len; i++) {
  doSomething(i);
  }

次のようにします。

var i = 0, limit;
while (i < len) {
  limit = (i+100);
  if (limit > len)
    limit = len;
  process.nextTick(function(){
     for (; i<limit; i++) {
      doSomething(i);
     }
    });
  }
}

これにより、ループの反復が 100 回実行され、制御がしばらくの間システムに戻され、終了するまで中断したところから再開されます。

編集:ここでは、特定のケースに合わせて調整されています(一度に実行する反復回数が引数として渡されます):

var forin = function(obj, callback, numPerChunk){
  var keys = Object.keys(obj);
  var len = keys.length;
  var i = 0, limit;
  while (i < len) {
    limit = i + numPerChunk;
    if (limit > len)
      limit = len;
    process.nextTick(function(){
        for (; i<limit; i++) {
          callback(keys[i], obj[keys[i]], obj);
        }
      });
  }
}
于 2011-11-03T22:51:47.503 に答える
-1

以下は [ブラウザ] JavaScript に適用されます。node.js とはまったく無関係かもしれません。


私が知っている2つのオプション:

  1. 複数のタイマーを使用してキューを処理します。それらはインターリーブし、「アイテムをより頻繁に処理する」という最終的な効果をもたらします(これは、より多くの CPU を盗む良い方法でもあります ;-)、または、
  2. カウントベースまたは時間ベースのいずれかで、サイクルごとにより多くの作業を行います。

Web Workers が適用可能/利用可能かどうかはわかりません。

ハッピーコーディング。

于 2011-11-03T17:16:17.453 に答える