16

私はノードが初めてで、ノードで非同期およびイベント動作の利点を使用しようとしています。私はノードから、イベントオブジェクトで処理するすべてのものを理解していましたが、それは非同期実行になります。
次に、これを試してみました。次のコードを検討してください。

var events = require("events");

var event = new events.EventEmitter();


event.on("work", function () {

    for (var i = 0; i <= 10; i++) {
        console.log("I do my work " + i);
    }

    event.emit("done");
});

var async = function (cb) {

    event.on("done", cb);
    event.emit("work");
    for (var i = 0; i <= 10; i++) {
        console.log("Async " + i);
    }
}


async(function () {
    console.log("I am done callback!");
});  

これは非同期実行ですか?私の意見では、いいえ!なぜ、私はこの文をたくさん読んだからです:

イベントが発生するので、行って何かをして、それが終わったら戻ってきて教えてください。その間、私は別のことをします。

ファースト フード レストランのシナリオのように。しかし、上記のコードでは、イベントが発生すると、次のシーケンスが発生します。

  1. コールバックに入ります
  2. ループを通過させる
  3. 出力 私は仕事をします n
  4. done イベントを発生させた
  5. 出力 I am done コールバック!
  6. 出力非同期 n

なぜコールバックが完了したのですか。Async n の前に出力しますか? ここがファストフード店のシナリオと違うのはなぜ?

作業イベントが発生し、行って作業を行い、完了したら戻ってきます。その間、Async n を出力します

これは、イベント駆動型の動作とノードの非同期について理解するために使用されます。しかし今、私はとても混乱しています。私が知っている、javascript はシングル スレッドで動作します。イベントエミッターを使用して非同期関数を作成するにはどうすればよいですか? しかし、イベントを発行するとすぐにハンドラーが実行されるため、不可能だと思います。

4

1 に答える 1

23

私はノードから、イベントオブジェクトで処理するすべてのものを理解していましたが、それは非同期実行になります。

これは正しくありません。イベントは同期的です。リスナーを追加すると、オブジェクトにコールバックが保存されます。

this._events[type].push(listener);

イベントを発行するときは、配列を反復して各リスナーを呼び出すだけです。

for (i = 0; i < len; i++)
      listeners[i].apply(this, args);

ソースコード: https://github.com/joyent/node/blob/master/lib/events.js

これは非同期実行ですか?私の意見では、いいえ!

あなたは正しいです。I/O 関数を呼び出したりsetImmediate、 、nextTickまたはタイマーを使用したりする場合は非同期です。それ以外の場合は同期です。非同期的に記述された同期コードは、非同期コードに変換されません。

なぜコールバックが完了したのですか。Async n の前に出力しますか?

「done」コールバックを受け取ると、「cb」を呼び出すためです。

event.on("done", cb);

戻るとcb、「Async n」ループが実行されます。

イベントエミッターを使用して非同期関数を作成するにはどうすればよいですか?

setImmediateまたはを使用しprocess.nextTickます。

「I do my work」ループの実行を延期したい場合は、行events.emit ("work")nextTick.

var events = require("events");

var event = new events.EventEmitter();


event.on("work", function () {

    for (var i = 0; i <= 10; i++) {
        console.log("I do my work " + i);
    }

    event.emit("done");
});

var async = function (cb) {

    event.on("done", cb);
    process.nextTick (function () {         //<-----
        event.emit("work");
    });                                     //<-----
    for (var i = 0; i <= 10; i++) {
        console.log("Async " + i);
    }
}


async(function () {
    console.log("I am done callback!");
});  

これは印刷されます:

Async 0
Async 1
Async 2
Async 3
Async 4
Async 5
Async 6
Async 7
Async 8
Async 9
Async 10
I do my work 0
I do my work 1
I do my work 2
I do my work 3
I do my work 4
I do my work 5
I do my work 6
I do my work 7
I do my work 8
I do my work 9
I do my work 10
I am done callback!
于 2013-07-19T08:24:50.750 に答える