nodejsの中のfiber(繊程)の倉庫は詳しく説明します.
8754 ワード
ファイバー
オペレーティングシステムには、プロセスとスレッドの他に、より少ない応用のためのプロセス(fiber)があります.プロセスはしばしばスレッドと比較して、オペレーティングシステムにとって、それらは比較的軽いクラスの動作状態である.一般に,スレッドよりも繊径が軽く,オーバーヘッドが小さいと考えられる.異なっているところは、繊程はスレッドあるいは繊程から創建したので、繊程のスケジューリングは完全にユーザーコードから制御して、システムのカーネルにとって、非占有性のスケジューリング方式で、繊程は協力式の多い任務を実現しました.スレッドとプロセスはカーネルによって優先され、優先順位によって占有型のマルチタスクが実現される.また、システムのカーネルは、繊程の具体的な運行状態を知らないので、繊程の使用は実は比較的にオペレーティングシステムと関係がありません.
nodeの中で、単一スレッドはjavascriptだけに対して、その下の層は実はマルチスレッドでいっぱいです.javascriptでマルチスレッドを実現する必要がある場合、よくあるやり方はC++addonを作成し、javascriptの単一スレッド機構をバイパスすることである.しかし、この方法は開発デバッグの難易度とコストを高めました.他の多くのシナリオ言語のように、私達も繊程の概念をnodeに導入することができます.
node-fibers
node-fibersのこの倉庫はnodeのために繊程の機能を提供しました.マルチスレッドについては、理想的な結果はテストされていませんでしたが、非同期的な作用が顕著で、node呼び出しスタックを減少させ、無限再帰的にも価値があるかもしれません.この文書では、node-fibersライブラリの使い方や非同期などを紹介します.
インストール
node-fibersはC言語で編纂されています.直接ソースをダウンロードするにはコンパイルが必要です.通常直接npmでインストールすればいいです.
API
1.ファイバー(fn)/new Fiber(fn):
繊程を作成します.構造関数としても使用できます.普通の関数としても呼び出されます.以下の例:
2.ファイバー.current:
現在のリードを取得し、動作します.変数を指定すると、その関連がある場合は、必ずこの繊維が解放されるようにしてください.でないと、V 8のゴミ回収メカニズムはこの部分のメモリをずっと無視してしまい、メモリが漏れてしまいます.
3.Fiber.yield(param):
前の説明でこの関数について言及しました.yield()方法は、繊程を中断するために用いられ、ある程度はreturnに似ている.一旦yieldを実行すると、このFiberの後続コードは実行できなくなります.例えば、
この方法はすでに熟知しています.前にはrun()を呼び出すという2つの時制がほのめかしていました.1つはファイバが起動していない時、一時的にはFiberがyieldに呼び出された時です.この二つの時制において、run()の行為はあまり同じではない.Fiberが起動していない場合、run()はパラメータを受け取り、fnに渡し、そのパラメータとして使用します.Fiberがyielding状態を処理する時、run()は一つのパラメータを受け入れて、yield()の戻り値として、fnは最初から運転するのではなく、中断から運転を続けます.fn、yield、runの3つのパラメータ、戻り値などの関係については、以下の例で説明することができます.
5.Fiber.prototype.reset():
Fiberは異なる時制が存在する可能性があり、同時にrunの行動に影響を与えることがわかっています.また、reset方法は、Fiberがどのような処理をしても、初期状態に戻ります.その後、runを実行すると、fnを再開します.
6.Fiber.prototype.throwInto(Exception):
本質的にはthrowIntoは、その異常を投げて、runの戻り値として異常情報を返します.Fiber内で投げられた異常を処理しないと、異常が持続します.異常かどうかは関係なく、強制的に処理し、Fiberを中断します.
futur e庫の使用
nodeの中で直接Fiberを使うのはずっと合理的ではありません.FiberのAPIは本当に簡単なので、実際に使うと重複した長いコードが発生し、維持に不利です.nodeとFiberの間に抽象的な層を追加して、Fiberをより良く作動させることを推奨します.futureライブラリはこのような抽象的なものを提供しています.futureライブラリやどのような抽象的な層も完璧ではないかもしれません.誰が間違っていません.適用だけが適用されますか?例えば、futureライブラリは、簡単なAPIを提供して、非同期化の作業を完了することができますが、それはgeneratorをカプセル化することができます.
futureライブラリは単独でインストールする必要はありません.すでにfibersライブラリに含まれています.使う時はvar future=require('fibers/future')だけが必要です.
API
1.Function.prototype.future():
Functionタイプにfutureメソッドを追加し、functionを一つの「funture-function」に変換します.
2.new Future()
Futureオブジェクトの構造関数については、以下に詳述する.
3.Future.wrap(fn,idx)
wrap方法は非同期動作をカプセル化しており、futur e庫の中で最も価値のある方法である.fnは変換が必要な関数を示し、IDxはfnが受け取るパラメータの数を表し、そのcalback方法は最後のパラメータであると考えています(ここのAPIの制定は論争があります.calbackがあるべき位置を伝える傾向があります.幸い、wrap方法は簡単で、コードを変更しやすいです).例を見れば、wrapの使い方が分かります.
4.Future.wait(futures):
この方法は前に何度も見ました.その名の通り、結果を待つのが役目です.もしfutureのインスタンスの結果を待つなら、直接にfuture Instance.waitを呼び出してもいいです.一連のfutureのインスタンスの結果を待つ必要があるなら、Future.waitを呼び出す.なお、第二の用法では、一つのfutureの例は運行中にエラーが発生し、waitの方法はエラーを出さないが、get()法を使って直接に運転結果を取得することができる.
5.Future.prototype.get():
get()の使い方はwait()の第一のやり方と似ていますが、違いはget()がすぐに結果に戻ります.データが準備されていないと、get()はエラーを投げます.
6.Future.prototype.resove(param 1、param 2):
上のwrap方法はいつも人に1種のfutureで実は非歩の方法を丸飲みしているコールバック関数をあげて、直接非歩の結果に帰ります.実際にfutureもresove法によってコールバック関数を設定するソリューションを提供します.resoliveは最大2つのパラメータを受け入れます.もし一つのパラメータだけが入ってきたら、futureはnodeスタイルのコールバック関数を伝えたと考えています.例えば、次のような例があります.
7.Future.prototype.isResolived():
ブール値を返します.動作が実行されたかどうかを示します.
8.Future.prototype.proxy(future Instance):
proxy方法はfutureの例のエージェントを提供し、本質的にはresove方法のパッケージであり、実はinstanceのフィードバック方法を別のinstanceのフィードバック実行者としている.たとえば:
9.Future.prototype.return(value):
10.Future.prototype.throw:
11.Future.prototype.recover():
12 Future.prototype.detach():
以上の四つのAPIは他のAPIに比べて、実際に使う場面や役割が一般的だと思います.returnとthrowはいずれもレレス方式によって管理されています.この3つの方法はすべて重要です.通常のfutureの使用プロセスでは黙々と作業していますが、私はそれらを単独で使うシーンは思いつかなかったので、具体的に紹介する方法はありません.detachの方法はresoliveの方法の簡略版を計算することしかできなくて、紹介の必要もありません.
オペレーティングシステムには、プロセスとスレッドの他に、より少ない応用のためのプロセス(fiber)があります.プロセスはしばしばスレッドと比較して、オペレーティングシステムにとって、それらは比較的軽いクラスの動作状態である.一般に,スレッドよりも繊径が軽く,オーバーヘッドが小さいと考えられる.異なっているところは、繊程はスレッドあるいは繊程から創建したので、繊程のスケジューリングは完全にユーザーコードから制御して、システムのカーネルにとって、非占有性のスケジューリング方式で、繊程は協力式の多い任務を実現しました.スレッドとプロセスはカーネルによって優先され、優先順位によって占有型のマルチタスクが実現される.また、システムのカーネルは、繊程の具体的な運行状態を知らないので、繊程の使用は実は比較的にオペレーティングシステムと関係がありません.
nodeの中で、単一スレッドはjavascriptだけに対して、その下の層は実はマルチスレッドでいっぱいです.javascriptでマルチスレッドを実現する必要がある場合、よくあるやり方はC++addonを作成し、javascriptの単一スレッド機構をバイパスすることである.しかし、この方法は開発デバッグの難易度とコストを高めました.他の多くのシナリオ言語のように、私達も繊程の概念をnodeに導入することができます.
node-fibers
node-fibersのこの倉庫はnodeのために繊程の機能を提供しました.マルチスレッドについては、理想的な結果はテストされていませんでしたが、非同期的な作用が顕著で、node呼び出しスタックを減少させ、無限再帰的にも価値があるかもしれません.この文書では、node-fibersライブラリの使い方や非同期などを紹介します.
インストール
node-fibersはC言語で編纂されています.直接ソースをダウンロードするにはコンパイルが必要です.通常直接npmでインストールすればいいです.
npm install fibers
ファイバーライブラリの使用API
1.ファイバー(fn)/new Fiber(fn):
繊程を作成します.構造関数としても使用できます.普通の関数としても呼び出されます.以下の例:
function fibo(n) {
return n > 1 ? fibo(n - 1) + fibo(n - 2) : 1;
}
Fiber(function () {
console.log(fibo(40));
});
run()が呼び出されたとき、繊程は起動し、fnに新しいスタックを割り当て、fnはこの新しいスタック上で動作し、fnが戻り値またはyield()を呼び出すまで動作する.fnが戻った後、またはyield()を呼び出した後、スタックはリセットされ、再度run()を起動すると、再度のトラフィックが開始され、fnは最初に割り当てられたスタックで動作する.2.ファイバー.current:
現在のリードを取得し、動作します.変数を指定すると、その関連がある場合は、必ずこの繊維が解放されるようにしてください.でないと、V 8のゴミ回収メカニズムはこの部分のメモリをずっと無視してしまい、メモリが漏れてしまいます.
3.Fiber.yield(param):
前の説明でこの関数について言及しました.yield()方法は、繊程を中断するために用いられ、ある程度はreturnに似ている.一旦yieldを実行すると、このFiberの後続コードは実行できなくなります.例えば、
var fiber = Fiber(function () {
console.log("Fiber Start");
Fiber.yield();
console.log("Fiber Stop");
}).run();
// : "Fiber Start"
実行後は「Fiber Start」のみ出力されますが、後の出力コマンドは実行されません.yield()にパラメータが入ると、このパラメータはrun()の戻り値として作用します.
var fiber = Fiber(function () {
Fiber.yield("success");
}).run();
console.log(fiber); // -> "success"
4.Fiber.prototype.run(param):この方法はすでに熟知しています.前にはrun()を呼び出すという2つの時制がほのめかしていました.1つはファイバが起動していない時、一時的にはFiberがyieldに呼び出された時です.この二つの時制において、run()の行為はあまり同じではない.Fiberが起動していない場合、run()はパラメータを受け取り、fnに渡し、そのパラメータとして使用します.Fiberがyielding状態を処理する時、run()は一つのパラメータを受け入れて、yield()の戻り値として、fnは最初から運転するのではなく、中断から運転を続けます.fn、yield、runの3つのパラメータ、戻り値などの関係については、以下の例で説明することができます.
var Fiber = require('fibers');
var fiber = Fiber(function (a) {
console.log(" run:");
console.log("fn :"+a);
var b = Fiber.yield("yield");
console.log(" run:");
console.log("fn :"+a);
console.log("yield :"+b);
return "return";
});
// run()
var c=fiber.run("One");
// run()
var d=fiber.run("Two");
console.log(" yield,run :"+c);
console.log("fn ,run :"+d);
出力は以下の通りです
/*
run:
fn :One
run:
fn :One
yield :Two
yield,run :yield
fn ,run :return
*/
上の例から、yieldの使い方は今のjavascriptの文法とかなり違っていることが分かります.他の言語では(C菗、Pythonなど)既にyieldのキーワードが実現されています.nodeの上でも1つのローズマリーを実現するとよくて、具体的にyieldの使用を体得します.最初のフィボナッチの数を例に挙げます.
var fiboGenerator = function () {
var a = 0, b = 0;
while (true) {
if (a == 0) {
a = 1;
Fiber.yield(a);
} else {
b += a;
b == a ? a = 1 : a = b - a;
Fiber.yield(b);
}
}
}
var f = new Fiber(fiboGenerator);
f.next = f.run;
for (var i = 0; i < 10; i++) {
console.log(f.next());
}
出力:
/*
1
1
2
3
5
8
13
21
34
55
*/
二つの問題があります.まず、yieldは方法と言います.キーワードのように、runと違って、yieldはFiberの実例に頼る必要がありません.runは必要です.Fiber内部でrunを呼び出すと、必ず使用します.第二に、yield自身はjavascriptの保留キーワードであり、いつ有効になるかは不明です.だから、コードは将来的に変更されるかもしれません.5.Fiber.prototype.reset():
Fiberは異なる時制が存在する可能性があり、同時にrunの行動に影響を与えることがわかっています.また、reset方法は、Fiberがどのような処理をしても、初期状態に戻ります.その後、runを実行すると、fnを再開します.
6.Fiber.prototype.throwInto(Exception):
本質的にはthrowIntoは、その異常を投げて、runの戻り値として異常情報を返します.Fiber内で投げられた異常を処理しないと、異常が持続します.異常かどうかは関係なく、強制的に処理し、Fiberを中断します.
futur e庫の使用
nodeの中で直接Fiberを使うのはずっと合理的ではありません.FiberのAPIは本当に簡単なので、実際に使うと重複した長いコードが発生し、維持に不利です.nodeとFiberの間に抽象的な層を追加して、Fiberをより良く作動させることを推奨します.futureライブラリはこのような抽象的なものを提供しています.futureライブラリやどのような抽象的な層も完璧ではないかもしれません.誰が間違っていません.適用だけが適用されますか?例えば、futureライブラリは、簡単なAPIを提供して、非同期化の作業を完了することができますが、それはgeneratorをカプセル化することができます.
futureライブラリは単独でインストールする必要はありません.すでにfibersライブラリに含まれています.使う時はvar future=require('fibers/future')だけが必要です.
API
1.Function.prototype.future():
Functionタイプにfutureメソッドを追加し、functionを一つの「funture-function」に変換します.
var futureFun = function power(a) {
return a * a;
}.future();
console.log(futureFun(10).wait());
実際にパワーアップ方法は、Fibel内で実行されます.ただし、既存バージョンのfutureにはbugがあります.公式には具体的な説明がありません.この機能を使うなら、future.jsの339行目と350行目を削除してください.2.new Future()
Futureオブジェクトの構造関数については、以下に詳述する.
3.Future.wrap(fn,idx)
wrap方法は非同期動作をカプセル化しており、futur e庫の中で最も価値のある方法である.fnは変換が必要な関数を示し、IDxはfnが受け取るパラメータの数を表し、そのcalback方法は最後のパラメータであると考えています(ここのAPIの制定は論争があります.calbackがあるべき位置を伝える傾向があります.幸い、wrap方法は簡単で、コードを変更しやすいです).例を見れば、wrapの使い方が分かります.
var readFileSync = Future.wrap(require("fs").readFile);
Fiber(function () {
var html = readFileSync("./1.txt").wait().toString();
console.log(html);
}).run();
この例から見ると、Fiberの非同期化は非常に効果的であり、文法的に一歩多くなりました.wait()以外に、fsで提供されたfs.readFileSync方法は他のものと変わりません.4.Future.wait(futures):
この方法は前に何度も見ました.その名の通り、結果を待つのが役目です.もしfutureのインスタンスの結果を待つなら、直接にfuture Instance.waitを呼び出してもいいです.一連のfutureのインスタンスの結果を待つ必要があるなら、Future.waitを呼び出す.なお、第二の用法では、一つのfutureの例は運行中にエラーが発生し、waitの方法はエラーを出さないが、get()法を使って直接に運転結果を取得することができる.
5.Future.prototype.get():
get()の使い方はwait()の第一のやり方と似ていますが、違いはget()がすぐに結果に戻ります.データが準備されていないと、get()はエラーを投げます.
6.Future.prototype.resove(param 1、param 2):
上のwrap方法はいつも人に1種のfutureで実は非歩の方法を丸飲みしているコールバック関数をあげて、直接非歩の結果に帰ります.実際にfutureもresove法によってコールバック関数を設定するソリューションを提供します.resoliveは最大2つのパラメータを受け入れます.もし一つのパラメータだけが入ってきたら、futureはnodeスタイルのコールバック関数を伝えたと考えています.例えば、次のような例があります.
futureInstance.resolve(function (err, data) {
if (err) {
throw err;
} else {
console.log(data.toString());
}
});
二つのパラメータが入ってきた場合、エラーとデータを別々に処理することを示す.
futureInstance.resolve(function (err) {
throw err;
}, function (data) {
console.log(data.toString());
});
また、futureは、resoliveの呼び出しタイミングを区分していません.データが準備されていない場合は、フィードバック関数をキューに押し込んで、reolver()の方法で統一的にスケジュールします.そうでなければ、直接データを取ってすぐにコールバック関数を実行します.7.Future.prototype.isResolived():
ブール値を返します.動作が実行されたかどうかを示します.
8.Future.prototype.proxy(future Instance):
proxy方法はfutureの例のエージェントを提供し、本質的にはresove方法のパッケージであり、実はinstanceのフィードバック方法を別のinstanceのフィードバック実行者としている.たとえば:
var target = new Future;
target.resolve(function (err, data) {
console.log(data)
});
var proxyFun = function (num, cb) {
cb(null, num * num);
};
Fiber(function () {
var proxy = Future.wrap(proxyFun)(10);
proxy.proxy(target);
}).run(); // 100
プロxyを実行しましたが、最終的にターゲットのコールバック関数が実行され、プロxyの実行結果でターゲットを駆動するコールバック関数です.このような代理手段は私達の実用的な応用に大きな役割を果たしているかもしれません.まだ深く考えたことがありません.9.Future.prototype.return(value):
10.Future.prototype.throw:
11.Future.prototype.recover():
12 Future.prototype.detach():
以上の四つのAPIは他のAPIに比べて、実際に使う場面や役割が一般的だと思います.returnとthrowはいずれもレレス方式によって管理されています.この3つの方法はすべて重要です.通常のfutureの使用プロセスでは黙々と作業していますが、私はそれらを単独で使うシーンは思いつかなかったので、具体的に紹介する方法はありません.detachの方法はresoliveの方法の簡略版を計算することしかできなくて、紹介の必要もありません.