Написать функцию async с помощью EventEmitter

Я новичок в node и стараюсь использовать преимущества async и поведения событий в node. Я использовал для понимания из node все, что обрабатывает объект Event, это будет асинхронное выполнение.
Тогда я попробовал это, рассмотрю следующий код:

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!");
});  

Это асинхронное выполнение? По-моему, нет! Почему, потому что я прочитал это предложение много:

Событие увольняется, поэтому идите и что-то делайте, а затем, когда вы закончите, придите назад и скажи мне, но пока я сделаю что-то еще.

Как сценарий ресторана быстрого питания. Но вышеприведенный код, когда событие будет запущено, произойдет следующая последовательность:

  • войдите в обратный вызов
  • пропустить цикл
  • Я делаю свою работу n
  • активировал выполненное событие
  • вывод завершен обратный вызов!
  • вывод Async n

почему я сделал обратный вызов! выйдет до Async n? Почему здесь не нравится сценарий ресторана быстрого питания, например

рабочее мероприятие уволено, идите, и вы делаете, и возвращаетесь, когда вы сделано, пока я выведу Async n

Это я использовал для понимания поведения, управляемого событиями, и асинхронизации в node. Но теперь я очень смущен. Я знаю, javascript работает в одном потоке. Как я могу написать функцию async с эмиттером событий? Но я думаю, что это невозможно, потому что, когда я испускаю событие, он немедленно выполнит обработчик.

Ответ 1

Я понял из node, все, что обрабатывает событие Event объект, это будет асинхронное выполнение.

Это неверно. События синхронны. Когда вы добавляете слушателя, вы просто сохраняете обратный вызов в объекте:

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

Это асинхронное выполнение? По-моему, нет!

Вы правы. Это асинхронно, если вы вызываете какую-либо функцию ввода-вывода или используете setImmediate, nextTick или таймер, в противном случае это синхронно. Синхронный код, написанный несинхронно, не преобразует его в асинхронный код.

почему я сделал обратный вызов! выйдет перед Async n?

Потому что, когда вы получаете "сделанный" обратный вызов, вы вызываете "cb":

event.on("done", cb);

Когда возвращается cb, выполняется цикл "Async n".

Как написать функцию async с эмитентом событий?

Использование setImmediate или process.nextTick.

Если вы хотите отложить выполнение цикла "Я делаю свою работу", вы можете обернуть строку 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!