2012-01-21 1 views
4

Node.jsでノンブロッキングコードを作成する方法を調べるために、たくさんの検索をしました。残念ながら、私が見つけたすべての例は、最終的にはすでにコールバックが組み込まれている関数に基づいています。だから私は自分の関数をコールバックで作成したかったのですが、何らかの理由でイベントループをブロックしていました。これは、イベントループブロックされませんでした:Node.js:イベントループをブロックしないで 'setTimeout'関数をどのように再作成しますか?

function foo(response){ 
    setTimeout(function(){ 
     response.writeHead(200, {"Content-Type": "text/plain"}); 
     response.write("bar"); 
     response.end(); 
    }, 7000); 
} 

をしかし、これはやった:私は、根本的な何か非ブロッキングコードの様相を

function foo(response){ 
    function wait(callback, delay){ 
      var startTime = new Date().getTime(); 
     while (new Date().getTime() < startTime + delay); 
     callback(); 
    } 
    wait(function(){ 
     response.writeHead(200, {"Content-Type": "text/plain"}); 
     response.write("bar"); 
     response.end(); 
    }, 7000); 
} 

行方不明ですか?

編集:

のsetTimeoutを再作成する私の目標は、私は私が、私も少し良くループを理解することができます試してみようと思いましたメンタルエクササイズの詳細です。今、私は、JavaScriptで生の処理をしているかなり重いサーバー側のコードがあると、イベントループを停止させないようにする方法を知りません。

答えを読んでもう少し考えてみると、より正確な質問が出てくる可能性があります。JavaScriptでサーバーを処理している場合、イベントループを中断する方法を教えてください?

私はここに初めて投稿したので、どんな反応が得られるのか分かりませんでした。これまでのところ、これは素晴らしいです。みんなありがとう。

編集2: お元気ですか、アドバイスありがとうございます。私はレイノスが提案したようにprocess.nextTickを試してみることになった。私は自分のノンブロッキングタイマーをコールバックで作成することができました。コードは完璧ではありませんが、興味がある人のために、これはそれがどのように見えるかです:

var timer = {}; 

function delay(callback, length){ 
    if(!timer.startTime){ 
     timer.startTime = new Date().getTime(); 
     timer.callback = callback; 
     timer.length = length; 
    } 
    if(new Date().getTime() < timer.startTime + timer.length){ 
     process.nextTick(delay); 
    } else { 
     timer.callback(); 
     timer = {}; 
    } 
} 

function list(response){ 
    delay(function(){ 
     console.log("callback"); 
     exec("dir", function (error, stdout, stderr) { 
      response.writeHead(200, {"Content-Type": "text/plain"}); 
      response.write(stdout); 
      response.end(); 
     }); 
    }, 7000); 
} 

は本当にこのコードを使用することを意図していません。しかし、これを行う方法を学ぶプロセスは、ノンブロッキングに関するいくつかの重要な概念を理解するのに役立ちました。

と非ブロッキングについてはまだ好奇心あなたのそれらのために、あなたはあなたのコードは、最終的にイベントループに戻り、それが処理を継続できるようにするために持っているイベントループを遮断しないようにするためにはRaynos' article.

+2

'bodyless while loop' ..."ノンブロッキングコードの基本的な側面は何ですか? –

+0

'setTimeout'を再作成しようとしてはいけません。ちょうどそれを使用してください。それはこの目的のために作られました。 – david

+0

私は、イベントループを継続させるためにsetTimeoutが何をするかをより深く理解することを考えました。 JavaScriptサーバ側で重い処理をしなければならないのであれば、私は同じ方法を使うことができます。 – Craig

答えて

3

をチェックアウトする必要があります。実際にコードがイベントループに戻るのでなければ、次のメッセージをデキューして処理することはできません。このコードは指定された時間だけ終了せず、イベントループに制御を戻しません。

+0

ああ、意味がある。私は本当にイベントのループについてはあまり知らないと思うけど、イベントのループを戻してチェックインするのはとにかくですか?たとえば、( "child_process")。execを使用すると、コールバックがありますが、まだ処理中であってもイベントループは停止しません。それはどうしたらできますか?自分の関数でそのメソッドを使うことはできますか? – Craig

+0

C#のWinFormsのような環境では、 'Application.DoEvents'を呼び出して手動でイベントループを呼び出すことができます。私はnode.jsにこれに慣れていないので、これを行う方法があるかどうかを知ることはできません。 – JaredPar

+1

@Craigあなたは 'process.nextTick'を呼び出して、イベントループの次のティックのコールバックをアタッチします。ノンブロッキング操作を行う他の唯一の方法は、ノードによって公開されたノンブロッキングAPIを使用するか、C++エクステンションを使用して独自のノンブロッキングapisを公開することです。 – Raynos

0

あなたは正しいアイデアを得ています。すばやく実行し、メインイベントループに制御を戻す関数を作成する必要があります。 (あなたの場合、文字通りwhileループに座ってスリープしている)関数自体の代わりに、通常はsetTimeoutでコールバックを登録してからリターンします。その後、タイムアウトが呼び出されると、それが復帰し、必要な機能を実行します。

function foo(response){ 
    function wait(callback, delay){ 
      var startTime = new Date().getTime(); 
     // this will block the event loop until this condition is true 
     while (new Date().getTime() < startTime + delay); 
     //then the callback is called 
     callback(); 
     //then it goes back to the event loop 
    } 
    wait(function(){ 
     response.writeHead(200, {"Content-Type": "text/plain"}); 
     response.write("bar"); 
     response.end(); 
    }, 7000); 
} 
0

おそらくラッパーは何ですか?

function wait(callback, delay){ 
    setTimeout(callback, delay); 
} 
+0

いくつかの機能を追加しない限り、それは実際に別名に似ています... –

+1

...と 'var wait = setTimeout;'ははるかに短くなります。 –

0

関数を呼び出すと、新しいスレッドは開始されません。したがって、wait関数の中でwhileループを実行すると、実行がブロックされます。

+0

ああ。つまり、setTimeoutや( "child_process")。execのようなものは、それぞれ独自のスレッドを作成しますか? – Craig

+0

@Craigいいえ... setTimeoutは、現在の時刻がスケジュールされた時刻を過ぎると、通常のイベントループで実行されるようにスケジュールを設定するだけです。子プロセスは、独自のスレッドではなく、独自のプロセスで実行されます。 – david

関連する問題