1

yieldどのように正確に動作するかを説明する適切なドキュメント (または SO に関する質問) が見つかりませんrun

を使用して非同期メソッドが値を返す方法を見つけることができませんFibers/futures

たとえば (コードが構文的に正しくない)、この関数をresponse同期的に返すにはどうすればよいですか?

  function findData( param )
  {
    var fiber = Fiber( function(){
      var currentFiber = Fiber.current;
      Model.findOne({ "param" : param}, function (err, data) {
        response = { err : err, data : data };
      });
    });
    return fiber;
  }

何かのようなもの

  var value = findData("1");

これModelは、スキーマ クラスから取得したオブジェクトですMongoose(関連性があるかどうかはわかりません)。

前もって感謝します。

4

2 に答える 2

1

関数を次のように変更します。

function findData(param) {
  var currentFiber = Fiber.current;
  Model.findOne({ "param" : param }, function(err, data) {
    if (err) fiber.throwInto(err);
    else fiber.run(data);
  });
  return Fiber.yield();
}

次に、次のように記述できます。

function doSomething() {
  var param = ...;
  var data = findData(param);
  processData(data);
}

function doLotsOfThings() {
  ...;
  doSomething();
  doSomethingElse();
}

Model.findOneなどなど...すべてのコードを同期のように書くことができます。

唯一の問題は、これらの関数をノードのイベント ループから直接呼び出すことができないことです。それらをファイバー内で呼び出す必要があります。通常、HTTP リスナー (または TCP リスナーなど) でファイバーを作成します。典型的なコード:

http.createServer(function(request, response) {
  // you cannot call doLotsOfThings() here
  Fiber(function() {
    // but you can call it here
    try { doLotsOfThings(); }
    // and this the right place to catch exceptions too!
    catch (ex) { handleException(ex); }
  }).run();
}).listen(8124);

つまり、Fiber.yield非同期関数を呼び出すときに低レベルで呼び出し (上記の最初のパターン)、最上位のリスナーでファイバーを作成します (上記の 2 番目のパターン)。その間のすべてのコードは同期スタイルで記述できます。

注: これらのコード パターンを使用すると、すべての関数でエラーをトラップ/テストする必要はありません。代わりに、従来の構造化された例外処理を使用できます (例外をバブルアップさせます)。

于 2016-09-26T21:33:25.333 に答える
1

繊維は新しい発明ではない

ノードファイバーは、現在実行中の環境の状態をプラットフォームに依存する方法で最低レベルに保存することにより、任意の機能の実行を一時停止することを可能にします (たとえば、Windows にはファイバーの概念があり、広く使用されておらず、スレッドよりも軽量であり、先制)。

他のライブラリは、言語機能を使用してコルーチンをシミュレートします

他のすべての js ライブラリは、コールバック関数を使用してコルーチン継続を実装し、実行状態をスコープ変数に格納します。これは、コールバック ピラミッド、Promise チェーン、または async/await (装飾されたジェネレーターを async/await と同じバケットに入れました) のいずれかがあることを意味します。

ファイバーは、コルーチンの可能な実装でもあります。ファイバーは高速である必要があり、それらをコードに統合するために、別のコード スタイルで記述したり、新しい構文を導入したりする必要はありません。独自のコードから自由に変更できる実行コンテキスト (スタック、レジスタなど)。

これは純粋な JavaScript では実行できません。ノード ファイバーはネイティブ ライブラリを使用してこれを実現します。

ノード ファイバーがユーザーを制限するため、イベント ループをブロックしません。

ノード ファイバー固有の概念は次のとおりです。javascript イベント ループはすべてのファイバーの外側にあるため、最初のコードもファイバーなしで実行されます。ファイバー参照がある場合は、実行する権利を で渡すことができますfiber.run();。ファイバーの内部にいる場合、呼び出すことで実行する権利を放棄することができFiber.yield();(現在実行中のコードを効果的に中断します)、javascript イベント ループが続行されます。すべての組み込みコールバック ( setTimeoutPromise.then、イベント ハンドラー、http 要求コールバック) は、ファイバーなしで JavaScript イベント ループで実行されます。

この例を参照してください

const Fiber = require("fibers");

function findDataAsync(param, callback) {
  setTimeout(() => {
    callback(null, "Async returned data");
  }, 100);
}

function findData( param ) {
  const currentFiber = Fiber.current;
  var response = null;

  findDataAsync(param, function (err, data) {
    response = { err : err, data : data };
    currentFiber.run();
  });
  Fiber.yield();
  if (response.err) {
    throw response.err;
  } else {
    return response.data;
  }
}


function main() {
  console.log("Inside fiber started");
  console.log(findData());
  console.log("Inside fiber finished");
}

console.log("Outside fiber started");
Fiber(main).run();
console.log("Outside fiber finished");

これにより、次のように出力されます。

Outside fiber started
Inside fiber started
Outside fiber finished
Async returned data
Inside fiber finished

Outside fiber finishedファイバーの最初の利回りが呼び出された直後に記録されることに注意してください。

ご覧のとおり、できるようにするために、ファイバーをすぐに開始する必要がありましたyield。サード パーティのライブラリでファイバーを使用しようとする場合は、setTimeout非同期の http 要求を呼び出したり発行したりして、ライブラリが現在の実行コンテキストを JavaScript イベント ループに「リセット」しないようにする必要があります。

于 2016-09-26T14:21:50.237 に答える