9

Node.jsが非同期で動作している間、次のように記述します。

function sleep() {
    var stop = new Date().getTime();
    while(new Date().getTime < stop + 15000) {
        ;
    }
}

sleep();
console.log("done");

... sleep()を呼び出し、whileループ(15秒)の間サーバーをブロックしてから、コンソールに「done」と出力します。私が理解している限り、これはNode.jsがJavaScriptにメインスレッドへのアクセスのみを許可しているためです。したがって、このようなことはそれ以上の実行を停止します。

だから私はこれに対する解決策がコールバックを使用することであることを理解しています:

function sleep(callback) {
    var stop = new Date().getTime();
    while(new Date().getTime() < stop + 15000) {
        ;
    }
    callback();
}

sleep(function() {
    console.log("done sleeping");
});

console.log("DONE");

だから私はこれが「DONE」と15秒後に印刷されると思いました。sleep()関数が呼び出され、コールバック関数へのポインターが渡されるため、「donesleeping」。この関数が機能している間(whileループ)、最後の行が実行されます(print'done')。15秒後、sleep()関数が終了すると、指定されたコールバック関数が呼び出され、「donesleeping」と出力されます。

どうやら私はここで何か間違っていることを理解しました、なぜなら上記の両方の方法がブロックするからです。誰か明確にしていただけますか?

よろしくお願いします、Slagjoeyoco

4

4 に答える 4

14

Javascriptとnode.jsはシングルスレッドです。つまり、単純なwhileブロックです。whileブロックが完了するまで、リクエスト/イベントを処理することはできません。コールバックはこの問題を魔法のように解決するのではなく、カスタムコードを関数に渡すのに役立つだけです。代わりに、を使用して繰り返しprocess.nextTickます。これにより、基本的に同じ結果が得られますが、リクエストとイベントも処理するためのスペースが残ります。つまり、ブロックされません。

function doSleep(callback) {
    var stop = new Date().getTime();

    process.nextTick(function() {
        if(new Date().getTime() < stop + 15000) {
            //Done, run callback
            if(typeof callback == "function") {
                callback();
            }
        } else {
            //Not done, keep looping
            process.nextTick(arguments.callee);
        }
    });
}

doSleep(function() {
    console.log("done sleeping");
    console.log("DONE");
});
于 2012-10-13T00:34:23.130 に答える
9

sleepすぐに呼び出しているので、新しいsleep関数がブロックされます。条件が満たされるまで繰り返しを続けます。setTimeout()ブロッキングを回避するために使用する必要があります。

setTimeout(function () {
    console.log('done sleeping');
}, 15000);
于 2012-10-13T00:26:51.767 に答える
2

コールバックは非同期性と同じものではありません。非同期操作から...コールバック...を取得する場合に役立ちます。あなたの場合、メソッドは引き続き同期的に実行されます。Nodeは、コールバックと長時間実行操作があることを魔法のように検出して、事前に返すようにするだけではありません。

実際の解決策はsetTimeout、別のスレッドでビジーループの代わりに使用することです。

于 2012-10-13T00:26:35.000 に答える
0

すでに述べたように、非同期実行はwhileではなくsetTimeout()によって実現する必要があります。これは、whileが1つの「実行フレーム」でフリーズするためです。

また、例に構文エラーがあるようです。

これは正常に機能します:http://jsfiddle.net/6TP76/

于 2012-10-13T00:33:24.097 に答える