8

10〜12のシミュレートされたリクエストごとに実行する必要のある重いデータ処理操作があります。より高いレベルの同時実行性については、Node.jsが優れたプラットフォームであり、非ブロッキングイベントループを持つことでそれを実現していることを読みました。

私が知っていることは、データベースのクエリなどを行うために、イベントを別のプロセス(mongod、などmysqld)に生成し、そのプロセスからの結果を処理するコールバックを作成できることです。けっこうだ。

しかし、コールバック内で大量の計算を実行したい場合はどうなりますか。そのコールバックのコードが完全に実行されるまで、他のリクエストをブロックしません。たとえば、高解像度の画像を処理したいのですが、コードはJavascript自体にあります(no separate画像処理を行うプロセス)。

私の実装の考え方は

get_image_from_db(image_id, callback(imageBitMap) {
    heavy_operation(imageBitMap); // Can take 5 seconds.
});

heavy_operationこれにより、ノードはこれらの5秒間リクエストを受け取ることができなくなります。それとも私はそのような仕事をするための間違った方法を考えていますか?ガイドしてください、私はJS初心者です。

アップデート

または、部分的な画像を処理し、イベントループに戻って他のコールバックを取り込んで、その部分的な画像の処理に戻ることができるようにすることもできます。(イベントの優先順位付けのようなもの)。

4

3 に答える 3

5

はい、コールバック関数はメインループで実行されるため、ブロックされます。ループをブロックしないのは、非同期的に呼び出される関数だけです。画像処理を非同期で実行したい場合は、別のプロセスを使用して実行する必要があることを理解しています。

それを処理するために独自の非同期プロセスを作成できることに注意してください。まず、Node.jsの非同期関数を作成する方法の回答を読むことができます。

アップデート

node.jsでノンブロッキング非同期関数を作成するにはどうすればよいですか?読む価値があるかもしれません。この質問は、実際には私がリンクした他の質問で参照されていますが、簡単にするためにここに含めると思いました。

于 2013-03-10T00:34:37.663 に答える
4

残念ながら、ニックの答えにコメントするのに十分なレピュテーションポイントはまだありませんが、ノードのクラスターAPIを調べましたか?現在はまだ実験段階ですが、複数のスレッドを生成できるようになります。

于 2013-03-10T02:00:14.493 に答える
4

コールバックで大量の計算が行われると、計算が完了するまでイベントループがブロックされます。これは、コールバックが5秒間イベントループをブロックすることを意味します。

私の解決策

ジェネレーター関数を使用して、イベントループに制御を戻すことができます。while loop長時間実行されるコールバックとして機能するために、3秒間実行されるを使用します。

ジェネレーター機能なし

let start = Date.now();

setInterval(() => console.log('resumed'), 500);
function loop() {
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds
        console.log('blocked')
    }
}

loop();

出力は次のようになります。

// blocked
// blocked
//
//  ... would not return to the event loop while the loop is running
//
// blocked
//...when the loop is over then the setInterval kicks in
// resumed
// resumed

ジェネレーター機能付き

let gen;
let start = Date.now();

setInterval(() => console.log('resumed'), 500);

function *loop() {
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds
        console.log(yield output())
    }
}

function output() {
    setTimeout(() => gen.next('blocked'), 500)
}

gen = loop();
gen.next();

出力は次のとおりです。

// resumed
// blocked
//...returns control back to the event loop while though the loop is still running
// resumed
// blocked
//...end of the loop
// resumed
// resumed
// resumed

javascriptジェネレーターを使用すると、計算中にイベントループに制御を戻す重い計算関数を実行するのに役立ちます。

イベントループの詳細については、 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*にアクセスしてください。

https://davidwalsh.name/es6-generators

于 2017-06-14T18:56:56.277 に答える