В узле многие объекты испускают события. Например, сервер TCP будет передавать событие «подключить» всякий раз, когда клиент запрашивает соединение, и, например, всякий раз, когда прочитана целая часть данных, файловая система будет передавать событие «данные». Эти объекты называются излучами событий в узле. Передатчик событий позволяет программистам подписаться на интересующие события и связывать функцию обратного вызова к соответствующим событиям, так что функция обратного вызова вызывается всякий раз, когда передатчик событий издает событие. Режим публикации/подписки очень похож на традиционный режим графического интерфейса, например, программа будет получать соответствующие уведомления при нажатии кнопки. Используя эту модель, серверные программы могут реагировать, когда произойдут некоторые события, такие как клиентское соединение, данные, доступные в сокете или закрытый файл.
Вы также можете создать свой собственный передатчик событий. Фактически, Node предоставляет специальный псевдо-класс EventEmitter, который можно использовать в качестве базового класса для создания собственного передатчика событий.
Понять режим обратного вызова
Асинхронное программирование не использует возвращаемые значения функции, чтобы указать конец функционального вызова, но принимает последующий стиль прохождения.
«Стиль продолжения продолжения» (CPS: стиль продолжения)-это стиль программирования, а управление процессом явно передается следующей операции ...
Функции в стиле CPS будут принимать функцию в качестве дополнительного параметра. Эта функция используется для явного указания на следующий процесс управления программой. Когда функция CPS вычисляет его «возвращаемое значение», она будет вызывать функцию, которая представляет следующий процесс программы, и воспринимать «возвращаемое значение» функции CPS в качестве параметра.
Из Википедии - http://en.wikipedia.org/wiki/contination-passing_style
В этом стиле программирования каждая функция будет вызывать функцию обратного вызова после выполнения, чтобы программа могла продолжать работать. Позже вы поймете, что JavaScript очень подходит для этого стиля программирования. Вот пример загрузки файлов в память под узлом:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.readfile ('/etc/passwd', function (err, filecontent) {
if (err) {
бросить ошибку;
}
console.log ('file content', filecontent.tostring ());
});
В этом примере вы передаете встроенную анонимную функцию в качестве второго параметра Fs.ReadFile. Фактически, это использует программирование CPS, потому что вы передаете последующий процесс выполнения программы функции обратного вызова.
Как видите, первым параметром функции обратного вызова является объект ошибки. Если в программе возникает ошибка, этот параметр станет экземпляром класса ошибок. Это общий шаблон для программирования CPS в узле.
Понять режим передатчика событий
В стандартном режиме обратного вызовов функция передается в качестве параметра для выполнения функции. Этот режим очень хорошо работает в сценариях, когда клиент должен быть уведомлен после завершения функции. Однако, если несколько событий происходят во время выполнения функции или событий несколько раз, этот шаблон не подходит. Например, если вы хотите получить уведомление каждый раз, когда сокет получает доступные данные, вы обнаружите, что стандартный режим обратного вызова не очень полезен в этом сценарии. В настоящее время режим передатчика событий пригодится. Вы можете использовать набор стандартных интерфейсов, чтобы четко разделить генератор событий и слушатель событий.
При использовании режима генератора событий участвуют два или более объектов - трансформаторы и одного или нескольких слушателей событий.
Передатчик событий, как следует из названия, является объектом, который может генерировать события. Слушатель событий - это код, связанный с передатчиком событий для прослушивания конкретных типов событий, например, следующий пример:
Кода -копия выглядит следующим образом:
var req = http.request (options, function (response) {
response.on ("data", function (data) {
console.log («Некоторые данные из ответа», Data);
});
response.on ("end", function () {
console.log («Ответ закончился»);
});
});
req.end ();
Этот код демонстрирует два необходимых шага при создании HTTP -запроса для доступа к удаленному HTTP -серверу с использованием API Node Node HTTP.Request (см. Главу более поздней). Первая строка принимает «стиль продолжения» (CPS: стиль прохождения продолжения), передавая встроенную функцию, которая будет вызвана, когда HTTP отвечает. API HTTP -запроса использует здесь CPS, потому что программа должна продолжать выполнять последующие операции после выполнения функции HTTP.Request.
Когда выполняется http.request, будет вызвана анонимная функция обратного вызова, а объект ответа HTTP передается в качестве параметра. Этот объект ответа HTTP является передатчиком событий. Согласно документу Node, он может издавать многие события, включая данные и конец. Функции обратного вызова, которые вы регистрируете, будут вызывать каждый раз, когда происходит событие.
В качестве урока используйте режим CPS, когда вам необходимо восстановить права на выполнение после завершения запрашиваемой операции, и используйте режим передатчика событий, когда события могут происходить несколько раз.
Понять типы событий
Переданные события имеют тип, представленный строкой. Предыдущий пример содержит два типа событий: «данные» и «конец», которые представляют собой любые строки, определяемые передатчиком событий. Тем не менее, традиционно определяет, что типы событий обычно состоят из строчных слов, которые не содержат пустых символов.
Вы не можете использовать код, чтобы сделать вывод, какие типы событий могут генерировать передатчик событий, потому что API передатчика событий не имеет механизма самоанализа, поэтому используемый вами API должен иметь документацию, чтобы указать, что он может издавать эти типы событий.
Как только событие произойдет, передатчик событий позвонит слушателю, связанному с событием, и передаст соответствующие данные слушателю в качестве параметра. В предыдущем примере http.Request функция обратного вызова «данных» принимает объект данных в качестве первого и единственного параметра, в то время как «End» не принимает никаких данных. Эти параметры как часть контракта API также субъективно определяются автором API. Подписи параметров этих функций обратного вызова также будут объяснены в документации API каждого излучателя событий.
Хотя передатчик событий - это интерфейс, обслуживающий все типы событий, событие «ошибка» является специальной реализацией в узле. Большинство передатчиков событий в узле будут генерировать событие «ошибки», когда в программе возникает ошибка. Если программа не прислушивается к событию «ошибки» передатчика событий, передатчик событий заметит и бросит непредучанное исключение вверх при возникновении ошибки.
Вы можете запустить следующий код в Node Perl, чтобы проверить эффект, который имитирует передатчик событий, который может генерировать два события:
Кода -копия выглядит следующим образом:
var em = new (require ('events'). eventemitter) ();
em.emit ('event1');
em.emit ('error', новая ошибка ('моя ошибка'));
Вы увидите следующий вывод:
Кода -копия выглядит следующим образом:
var em = new (require ('events'). eventemitter) ();
неопределенный
> em.emit ('event1');
ЛОЖЬ
> em.emit ('error', new Error ('моя ошибка'));
Ошибка: моя ошибка
в Repl: 1: 18
at Replserver.eval (Repl.js: 80: 21)
в Repl.js: 190: 20
at Replserver.eval (Repl.js: 87: 5)
в интерфейсе. <Anonymous> (Repl.js: 182: 12)
at interface.emit (Events.js: 67: 17)
at interface._online (readline.js: 162: 10)
at interface._line (readline.js: 426: 8)
at interface._ttywrite (readline.js: 603: 14)
at Readstream. <Anonymous> (readline.js: 82: 12)
>
Во втором строке кода событие, называемое «Event1», испускается без какого -либо эффекта, но когда испускается событие «ошибки», ошибка выводит в стек. Если программа не работает в среде командной строки Perl, программа будет разрушена из -за непредучаного исключения.
Использование API передатчика событий
Любой объект, который реализует режим передатчика событий (такой как сокет TCP, HTTP -запрос и т. Д.), реализует следующий набор методов:
Кода -копия выглядит следующим образом:
.AddListener и .on - добавьте слушатель событий для событий указанного типа
.once - свяжите прослушивателя событий, который выполняет только один раз для события указанного типа
.RemoveEventListener - Удалить слушателя, связанный с указанным событием
.RemovealleventListener - Удалить всех слушателей, связанных с указанным событием
Давайте представим их подробно ниже.
Функции привязки обратного вызова с использованием .addlistener () или .on ()
Указав тип события и функцию обратного вызова, вы можете зарегистрировать действия, выполняемые при событии. Например, если есть доступные блоки данных, когда файл считывает поток данных, он излучит событие «данных». Следующий код показывает, как пройти функцию обратного вызова, чтобы программа сообщила вам, что событие данных произошло.
Кода -копия выглядит следующим образом:
Функция mESTATA (data) {
console.log («Получил данные из потока чтения файлов: %j», data);
}
readstream.addlistener ("Data", Recematata);
Вы также можете использовать .on, что является только аббревиатурой .AddListener. Следующий код такой же, как и выше:
Кода -копия выглядит следующим образом:
Функция mESTATA (data) {
console.log («Получил данные из потока чтения файлов: %j», data);
}
readstream.on ("Data", Recetata);
В предыдущем коде вы можете использовать именованную функцию, определенную заранее в качестве функции обратного вызова, и вы также можете использовать встроенную анонимную функцию для упрощения кода:
Кода -копия выглядит следующим образом:
readstream.on ("data", function (data) {
console.log («Получил данные из потока чтения файлов: %j», data);
});
Как упоминалось ранее, количество параметров и подписей, передаваемых в функцию обратного вызова, зависит от конкретного объекта передатчика событий и типа события. Они не стандартизированы. Событие «Data» может пройти объект буфера данных, событие «ошибка» передает объект ошибки, а событие «конечного» потока данных не передает никаких данных слушателю события.
Связывать несколько слушателей событий
Режим передатчика событий позволяет нескольким слушателям событий прослушать один и тот же тип события одного и того же передатчика событий, например:
Кода -копия выглядит следующим образом:
У меня есть некоторые данные здесь.
У меня здесь тоже есть данные.
Передатчик событий отвечает за ссылку на все слушатели, связанные с указанным типом события в порядке, в котором прослушитель зарегистрирован, то есть:
1. Когда происходит событие, слушателя событий не может быть вызван немедленно, и могут быть вызваны другие слушатели событий перед ним.
2. Это ненормально, чтобы быть брошенным в стек, что может быть из -за ошибки в коде. Когда событие передается, если слушатель событий бросает исключение при его вызове, некоторые слушатели событий никогда не могут быть вызваны. В этом случае передатчик событий завоевывает исключение и может также справиться с ним.
См. Следующий пример:
Кода -копия выглядит следующим образом:
readstream.on ("data", function (data) {
Выбросить новую ошибку («что -то не так произошло»);
});
readstream.on ("data", function (data) {
console.log («У меня здесь тоже есть данные.»);
});
Поскольку первый слушатель бросает исключение, второй слушатель не будет вызван.
Используйте .Removelistener () для удаления слушателя событий из передатчика событий
Если вы больше не заботитесь о событии на объекте, вы можете отменить зарегистрированного слушателя событий, указав тип события и функцию обратного вызова, например:
Кода -копия выглядит следующим образом:
Функция mESTATA (data) {
console.log («Получил данные из потока чтения файлов: %j», data);
}
readstream.on ("Data", Recetata);
// ...
readstream.removelistener («Data», Recematata);
В этом примере последняя строка удаляет слушателя событий, который может быть вызван в любое время в будущем из объекта передатчика событий.
Чтобы удалить слушателя, вы должны назвать функцию обратного вызова, потому что имя функции обратного вызова требуется при добавлении и удалении ее.
Используйте .once (), чтобы включить функцию обратного вызова не раз один раз
Если вы хотите прослушать событие, которое выполняется не более одного раза, или интересно только в первый раз, когда произойдет событие, вы можете использовать функцию .once ():
Кода -копия выглядит следующим образом:
Функция mESTATA (data) {
console.log («Получил данные из потока чтения файлов: %j», data);
}
readstream.once ("Data", Recetata);
В приведенном выше коде функция «Пометания» будет вызвана только один раз. Если объект ReadStream издает событие данных, функция обратного вызова mecitata будет и запустить только один раз.
На самом деле это просто удобный метод, потому что он может быть реализован очень просто, например, это:
Кода -копия выглядит следующим образом:
var EventEmitter = require ("События"). EventEmiter;
Eventemitter.prototype.once = function (type, callback) {
var that = это;
this.on (type, function usinger () {
что. РЕМОВЕЛИСТЕР (тип, слушатель);
callback.apply (это, аргументы);
});
};
В приведенном выше коде вы переопределяете функцию EventEmitter.prototype.once, а также переопределяете некогда функцию каждого объекта, унаследованного от EventEmitter. Код просто использует метод .on (). Как только событие будет получено, используйте .RemoveEventListener (), чтобы отменить регистрацию функции обратного вызова и вызовите исходную функцию обратного вызова.
ПРИМЕЧАНИЕ. Предыдущий код использует метод function.apply (), который принимает объект и принимает его как содержащую эту переменную и массив параметров. В предыдущем примере массив параметров, прозрачный, передается в функцию обратного вызова через передатчик событий.
Удалить всех слушателей мероприятий из передатчика событий с помощью .Removealllisteners ()
Вы можете удалить всех слушателей, зарегистрированных в указанном типе события из передатчика событий следующим образом:
Кода -копия выглядит следующим образом:
Emitter.Removealllisteners (type);
Например, вы можете отменить слушателя всех сигналов прерывания процесса, подобных этим:
Кода -копия выглядит следующим образом:
Process.Removealllisteners ("Sigterm");
Примечание. В качестве урока рекомендуется использовать эту функцию только тогда, когда вы точно знаете, что удалено. В противном случае вы должны позволить другим частям приложения удалить коллекцию слушателей событий, или вы также можете позволить этим частям программы взять на себя ответственность за устранение слушателя сами. Но независимо от того, что эта функция по -прежнему полезна в некоторых редких сценариях, например, когда вы готовитесь закрыть передатчик событий или упорядочительно закрывать весь процесс.
Создать передатчик событий
Передатчики событий делают интерфейсы программирования более общими. В общем и простом в режиме программирования клиент напрямую вызывает различные функции, в то время как в режиме передатчика событий клиент связан с различными событиями, что сделает вашу программу более гибкой. (Примечание переводчика: это предложение не очень уверенно, публикуя исходный текст: эмиттер событий обеспечивает отличный способ сделать интерфейс программирования более общим. Когда вы используете общий шаблон понимания, клиенты связываются с событиями, а не вызывает функции, что делает вашу программу более гибкой.)
Кроме того, используя передатчики событий, вы также можете получить много функций, таких как связывание нескольких не связанных слушателей на одном и том же событии.
Унаследован от передатчика событий узла
Если вы заинтересованы в режиме излучения событий Node и намереваетесь использовать его в своем собственном приложении, вы можете создать псевдо-класс, унаследовав EventEmitter:
Кода -копия выглядит следующим образом:
util = require ('util');
var EventEmitter = require ('events'). EventEmiter;
// это конструктор MyClass:
var myclass = function () {
}
util.inherits (myclass, eventemitter);
Примечание: util.inherits создает прототипную цепочку MyClass, так что ваш экземпляр MyClass может использовать метод прототипа EventEmitter.
Запуск события
Унаследовав от Eventemitter, MyClass может запустить такие события, как это:
Кода -копия выглядит следующим образом:
Myclass.prototype.somemethod = function () {
this.emit ("Custom Event", "Аргумент 1", "Аргумент 2");
};
В приведенном выше коде, когда метод Somemethond вызывается экземпляром MyClass, будет испускается событие под названием «Citilom Event». Это событие также излучит две строки в виде данных: «Аргумент 1» и «Аргумент 2», который будет передаваться в качестве параметров для слушателя событий.
Клиент экземпляра MyClass может прослушать событие "Custom Event", как это:
Кода -копия выглядит следующим образом:
var myinstance = new myclass ();
myinstance.on ('Custom Event', function (str1, str2) {
console.log ('получил пользовательское событие с Str1 %s и Str2 %s!', Str1, Str2);
});
Например, вы можете создать класс тикеров, который излучает события «Тик» один раз в течение секунды:
Кода -копия выглядит следующим образом:
var util = require ('util'),
EventEmitter = require ('Events'). EventEmitter;
var ticker = function () {
var self = это;
setInterval (function () {
self.emit ('tick');
}, 1000);
};
util.inherits (тикер, Eventemitter);
Клиенты, использующие класс тикеров, могут показать, как использовать класс тикеров и слушать события «Tick».
Кода -копия выглядит следующим образом:
var ticker = new Ticker ();
ticker.on ("tick", function () {
console.log ("tick");
});
краткое содержание
Режим передатчика событий - это шаблон повторного положения, который можно использовать для отделения объекта передатчика событий из набора кода для конкретного события.
Вы можете использовать Event_emiter.on () для регистрации слушателей для конкретных типов событий и Unregister с event_emiter.removelistener ().
Вы также можете создать свой собственный излучение событий, унаследовав EventEmitter и просто используя функцию .emit ().