2013-07-19 2 views
12

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

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. вывод я делаю свою работу н
  4. уволили сделано событие
  5. мощность я сделан обратный вызов!
  6. выход Асинхронный п

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

событие работы уволят, пойти и сделать вас вещи и вернуться, когда вы сделано, в то же время я буду выходной Async п

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

ответ

18

Я использовал для понимания из узла, все, что обрабатывает объект 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 или таймер, иначе он синхронный.Синхронный код, написанный asynchrously, не преобразует его в асинхронный код.

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

Потому что, когда вы получаете «сделано» обратного вызова вы звоните в «Си-Би»:

event.on("done", cb); 

Когда cb возвращается, цикл «Асинхронный п» выполняется.

Как написать функцию 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! 
+0

Цикл событий будет выполняться снова, после того, как коды в стеке было завершено. Например, у меня есть 3 строки кода. Первый - process.nextTick (dosomething) и другие просто console.log («что-то») ;. Тогда цикл событий будет выполнен правильно? И в начале этого цикла будет выполняться обратный вызов, зарегистрированный в process.nextTick(). Правильно? –

+0

Посмотрите на следующий код, когда я звоню/test1 и в другом браузере/test2, ему нужно долгое время получить ответ на/test2, для меня это похоже на/test1 block/test2 var express = require ('express'); var app = express(); app.get ('/', function (req, res) { res.send ('Hello World'); }); app.get ('/ test1', функция (REQ, разреш) { \t \t для (вар я = 0; г <= 100000000000; я ++) { \t \t \t} res.send ('The цикл завершен '); }); app.get ('/ test2', function (req, res) { res.send ('No loop'); }); app.listen (3000); console.log («Экспресс начался на порте 3000»); –

+2

/test1 «блокирует» цикл событий. Вот почему узел не для интенсивных задач процессора. Вы можете создать новый процесс и выполнить эти задачи. Прочтите эту статью, чтобы полностью понять параллелизм в узле: http://neilk.net/blog/2013/04/30/why-you-should-use-nodejs-for-CPU-bound-tasks/ –