0

イベントとイベントループがどのように機能するかを理解するために長い間試みました。イベント登録とイベント ループに関するインターネットや書籍の記事をたくさん読みましたが、まだそれがどのように機能するのか想像できません。

イベント キューに関する本 Async JavaScript を Prgmatic Bookshelft から読んでいます。この本で記事を読むことができます。

setTimeout を呼び出すと、タイムアウト イベントがキューに入れられます。その後、setTimeout 呼び出しの後のコードが実行され、コードがなくなるまで実行が続けられます。その後、イベント ループが開始され、どのイベントが発生したかが検出され、ハンドラーが呼び出されます。

この記事の後、Javascript のイベントと非同期について少し想像力がつきました。次に、次のコードを自分で試しました。

setTimeout(function(){alert("Hello")},0);

for (var i = 0; i <= 100000; i++) {
    console.log('I am loop');
}

この文について確認したいので、時間を 0 に設定しました。

setTimeout 呼び出しが実行された後のコードなど。

その後、イベントループが開始され、...

ここまでは、Javascript のイベントで問題ありません。できます。それから、私は Async JavaScript の本を読み続け、以下を読みました:

入力イベントも同じように機能します。ユーザーがクリック ハンドラーがアタッチされた DOM 要素をクリックすると、クリック イベントがキューに入れられます。ただし、現在実行中のすべてのコードが終了するまで、ハンドラーは実行されません。

最初の文は、私には少し混乱しているように聞こえます。例えば:

//Some codes
#("element").click(function(e){
    //Do something
});
//Some codes

ここで理解できないのは、コンパイラがクリック イベントをイベント キューに保存するタイミングです。登録後 (このコードの後)、または要素をクリックしたときにキューに保存されますか?

ノードで、イベントがどのように機能するかを理解するために、このコードを試しました。次のコードを検討してください。

var events = require("events");
var event = new events.EventEmitter();

event.on('ev1', function () {
    console.log('Into ev1');

});

event.emit('ev1');
for (var i = 0; i <= 5; i++) {
    console.log('I am in the loop');
}

console.log('I am finish with loop');

ここで期待されるのは次のとおりです。

私はループ
にいます
私はループにいます
私はループにいます 私はループにいます 私はループにいます 私
はループにいます
私はループにいます ev1
にループします

しかし、私が得たのは次のとおりです。

ev1
へ ループ
中 ループ中
ループ中
ループ中
ループ中
ループ
で終了

この出力の後、以前に本やネットの記事で読んだイベント (非同期) の実行とイベント ループに関する私の想像をすべて破ります。本の中の次の文を考えてみましょう。

setTimeout 呼び出しの後のコードが実行され、コードがなくなるまで続きます。その後、イベント ループが開始され、どのイベントが発生したかが検出され、ハンドラーが呼び出されます。

しかし、なぜ上記のコードはEventEmitter逆に動作するのでしょうか? イベントループは最後に実行されると思いました(他のコードが実行された後)。

ノードが非同期のデータベース(マングースなど)クエリについてインターネットで読んだことがあります。非同期データベースクエリがどのように機能するかはわかりませんが、次のように想像しています:

データベースのリクエストとレスポンス

Javascript のイベントが実際にどのように機能するのか、説明してください。

4

1 に答える 1

1

setTimeoutは から少し離れてEventEmitterいるため、これらの結果が得られます。まず、これらの例を最初に実行してください。

これを async.html に保存し、ブラウザで実行します。コンソールをチェックして結果を確認します。

<div id="element">
</div>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
setTimeout(function(){console.log("Hello")},0);
$("#element").click(function(e){
    console.log("Inside");
});
$("#element").click();
for (var i = 0; i < 5; i++) {
    console.log('I am loop');
}
</script>

出力

Inside
I am loop
I am loop
I am loop
I am loop
I am loop
Hello

これを async.js に保存し、node.js で実行します

setTimeout(function(){console.log("Hello")},0);

for (var i = 0; i < 5; i++) {
    console.log('I am loop');
}

出力

I am loop
I am loop
I am loop
I am loop
I am loop
Hello

setTimeoutとは少し異なる動作をすることがわかりますEventEmitter。EventEmitter はハンドラーをすぐに実行しますが、setTimeout はすぐに実行しようとします。アクションは次のティックまで実行されません。ここでそれについて読んでください

setTimeout と EventEmitter を混在させないでください。

編集

あなたの例は、非同期性を十分に示していません。イベントハンドラー内でループを実行しているだけです。より明確な例を次に示します。

var events = require("events");
var event = new events.EventEmitter();

event.on("work", function (i,cb) {
    console.log('Started '+i );
    setTimeout(function(){event.emit("done",i,cb);},Math.random()*1000);
});

event.on("done", function (i,cb) {
    cb(i);
});

var async = function (cb) {
    for (var i = 0; i <= 100; i++) {
        emitclosure(i,cb);
    }
}

function emitclosure(i,cb){
        setTimeout(function(){event.emit("work",i,cb)},Math.random()*1000);
}

async(function (i) {
    console.log("I have done "+i);
});

setTimeout質問での同義語の使用とは異なり、イベントと一緒に使用して、作業の到着の遅延と処理の遅延の感覚を与えるためだけに使用していることを指摘します。emitclosureスコープが安全であるように、ループ変数の単なるクロージャです。

于 2013-07-18T10:54:26.777 に答える