0

Redis を使用して、メモリ内に格納されたモデルの ID を生成しています。Redis クライアントには、INCRコマンドへのコールバックが必要です。つまり、コードは次のようになります。

client.incr('foo', function(err, id) {
  ... continue on here
});

incr問題は、呼び出しが同期的で ID を返すことを期待するアプリの他の部分を既に作成しているため、次のように使用できることです。

var id = client.incr('foo');

この問題が発生した理由は、これまで、次のような単純なクロージャー カウンター関数を使用してメモリ内で ID を生成していたためです。

var counter = (function() {
  var count = 0;
  return function() {
    return ++count;
  }
})();

テストと一般的なセットアップだけを簡素化します。

これは、私のアプリに設計上の欠陥があり、ID の生成時にコールバックを期待するように書き直す必要があるということですか? または、呼び出しを同期する簡単な方法はありますか?

4

4 に答える 4

3

Node.js は本質的に非同期 I/O ライブラリ(プラグイン付き) です。したがって、定義上、そこには同期 I/O がないため、アプリを書き直す必要があります。

于 2012-05-05T14:22:04.580 に答える
2

少し面倒ですが、カウンターが生成された後のロジックを関数にラップし、それを Redis コールバックから呼び出す必要があります。あなたがこのようなものを持っていたら:

var id = get_synchronous_id();
processIdSomehow(id);

このようなことをする必要があります。

var runIdLogic = function(id){
  processIdSomehow(id);
}

client.incr('foo', function(err, id) {
  runIdLogic(id);
});

適切なエラーチェックが必要ですが、そのようなものがうまくいくはずです。

Node 用のシーケンシャル プログラミング レイヤー ( TameJSなど) がいくつかありますが、これらは通常、再コンパイルなどを行います。彼ら。

于 2012-05-05T14:35:11.907 に答える
0

@Sergioは彼の回答でこれを簡単に述べましたが、もう少し拡張された回答を書きたかったのです。node.js は非同期設計です。これは単一のスレッドで実行されます。つまり、高速性を維持し、多くの同時操作を処理するには、すべてのブロッキング呼び出しに戻り値を非同期で実行するためのコールバックが必要です。

これは、同期呼び出しができないという意味ではありません。それらはそうであり、サードパーティのプラグインをどのように信頼するかについての懸念です. 誰かがプラグインでブロックする呼び出しを作成することを決定した場合、あなたはその呼び出しに翻弄され、API で公開されていない内部的なものでさえある可能性があります。したがって、アプリ全体がブロックされる可能性があります。Redis が戻るのにかなりの時間がかかった場合に何が起こるかを考えて、同じルーチンにアクセスしている可能性のあるクライアントの量を掛けます。ロジック全体がシリアル化され、すべて待機します。

最後の質問への回答として、ブロッキング アプローチに対応する方向に進むべきではありません。今では単純な解決策のように思えるかもしれませんが、そもそも node.js の利点に反するものです。同期設計ワークフローに慣れている場合は、そのように設計された別のフレームワーク (スレッドを使用) を検討することをお勧めします。node.js に固​​執する場合は、コールバック スタイルに準拠するように既存のロジックを書き直してください。私が見たコード例から、再帰スタックから戻ることができるまで、コールバックがコールバックなどを使用するため、ネストされた一連の関数のように見える傾向があります。

于 2012-05-05T15:12:58.783 に答える
0

node.js のアプリケーションの状態は、通常、オブジェクトとして渡されます。私がすることは、次のことに近いです。

var state = {}

client.incr('foo', function(err, id) {
  state.id = id;
  doSomethingWithId(state.id);
});

function doSomethingWithId(id) {
  // reuse state if necessary
}

やり方が違うだけです。

于 2012-05-05T18:54:31.867 に答える