Как легко использовать генераторы событий с ES5 и ES6 в Node.js

В настоящее время существует множество библиотек с открытым исходным кодом, которые вы можете использовать в своих проектах. Они довольно хорошо сработали и позволяют вам делать много вещей, чтобы знать, когда что-то происходит через события. Они позволяют вам, как правило, добавлять обратный вызов к определенным событиям, вызываемым внутри. Задумывались ли вы, что является правильным и простым способом создания такой библиотеки, которая позволяет использовать обратные вызовы? Хорошо, если это правильный путь, это не абсолютная истина, но многие библиотеки полагаются на класс Event Emitter Node.js.

Все объекты, которые генерируют события, являются экземплярами класса EventEmitter, эти объекты предоставляют eventEmitter.on() функция, которая позволяет прикрепить одну или несколько функций к именованным событиям, испускаемым объектом. Как правило, имена событий представляют собой строки в верблюжьей оболочке, но можно использовать любой допустимый ключ свойства JavaScript.

В этой статье вы узнаете, как использовать их для ECMAScript 5 и 6.

ES5

Если вы используете ECMAScript 5, использование отправителей событий не может быть настолько очевидным для начинающих в Javascript:

// yourLibrary.js
// Instantiate event emitter and inherits
var EventEmitter = require('events');
var inherits = require('util').inherits;
// Create the constructor of YourLibrary and add the EventEmitter to the this context
function YourLibrary() {
EventEmitter.call(this);
}
// Use Inheritance to add the properties of the DownloadManager to event emitter
inherits(YourLibrary, EventEmitter);
// Export YourLibrary !
module.exports = YourLibrary;

когда EventEmitter.call(this) выполняется при создании экземпляра из YourLibrary, он добавляет свойства, объявленные из конструктора EventEmitter к YourLibrary, Затем функция наследует наследует методы-прототипы от одного конструктора в другой (ваш конструктор YourLibrary и супер-конструктор EventEmitter), таким образом, прототип вашего конструктора будет установлен на новый объект, созданный из superConstructor.

Поскольку ваша библиотека, очевидно, не будет предлагать те же методы EventEmitter, вам нужно добавить свои собственные функции в YourLibrary с помощью прототипирования до или после module.exports линия:

//yourLibrary.js
YourLibrary.prototype.testAsyncMethod = function testAsyncMethod(someData) {
_this = this;
// Execute the data event in 2 seconds
setTimeout(function(){
// Emit the data event that sends the same data providen by testAsyncMethod
_this.emit("data", someData);
}, 2000);
};

Предыдущая функция добавляет testAsyncMethod для вашей библиотеки этот метод ожидает некоторые данные в качестве первого аргумента, и он будет снова отправлен через событие данных, отправленное с помощью унаследованного метода emit из класса EventEmitter. В этом случае YourLibrary использует менеджер событий Node.js и может быть использован для создания организованного и легко читаемого кода:

// otherfile.js
// Require YourLibrary file
var YourLibrary = require("./yourLibrary");
// Create an instance of YourLibrary
var libInstance = new YourLibrary();
// Add the "data" event listener to your library and add some callback
libInstance.on("data", function(data){
// Outputs: "Hello World, data test"
console.log(data);
});
// Execute the testAsyncMethod of your library
libInstance.testAsyncMethod("Hello World, data test");

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

ES6

В EcmaScript 6 эта задача была действительно упрощена, и ее довольно легко обрабатывать и понимать, чем в ES5. Однако он работает аналогичным образом: используя ключевое слово extends, ваш класс может расширять EventEmitter, наследуя, очевидно, его метод и, следовательно, может использовать метод emit для запуска события:

const EventEmitter = require('events');
class YourLibrary extends EventEmitter {
constructor() {
super();
}
testAsyncMethod(data) {
this.emit('data', data);
}
}
module.exports = YourLibrary

затем YourLibrary может быть легко использован из другого файла:

const MyLibrary = require('./yourLibrary');
const libInstance = new MyLibrary();
libInstance.on('data', (data) => {
// Outputs : Received data: "Hello World, data test"
console.log(`Received data: "${data}"`);
});
libInstance.testAsyncMethod("Hello World, data test");

Как видите, это намного проще, чем обрабатывать тот же код с ES6.

Пример использования ECMAScript 5

Если вы не получили его с введением, не беспокойтесь, мы уверены, что обращение с примером как библиотекой в ​​реальной жизни (или чем-то похожим) поможет вам понять. В этом примере представьте, что мы собираемся использовать библиотеку Download Manager, эта библиотека действительно простая, она предлагает способ асинхронной загрузки файла с вашего сервера. Используя класс Event Emitters файла Node.js, вы можете узнать, когда заканчивается загрузка файла, и узнать о ходе загрузки.

Пример ничего не загружает на самом деле, мы просто моделируем загрузку, используя setInterval (за progress событие) и setTimeout (за downloadSuccess событие) функция. Создать fileDownloader.js в какую-то папку вашего рабочего пространства и добавьте следующий код:

// fileDownloader.js
var EventEmitter = require('events');
var inherits = require('util').inherits;
// Create the constructor of DownloadManager and add the EventEmitter to the this context
function DownloadManager() {
EventEmitter.call(this);
}
// Use Inheritance to add the properties of the event emitter to DownloadManager
inherits(DownloadManager, EventEmitter);
// Export the Download Manager
module.exports = DownloadManager;
//
// Write your library down here by prototyping !
//
/**
* @param URL {String} Url of the imaginary file to download
*/
DownloadManager.prototype.downloadAsync = function downloadAsync(URL) {
var _this = this;
var progress = 0;
console.log('Download file "' + URL + '" ...');
// Trigger the progress event every second
var progressInterval = setInterval(function() {
progress += 20;
// Emit progress event with the progress as argument
_this.emit('progress' , progress);
}, 1000);
// Trigger the downloadSuccess event in 5.5 seconds and clear the progress interval
setTimeout(function() {
var optionalDataResponse = {
filename: "imaginary.txt",
filesize: 123123,
fileUrl: URL
};
// Stop triggering progress
clearInterval(progressInterval);
// Use the emit method of the EventEmitter to trigger the downloadSuccess event !
_this.emit('downloadSuccess' , optionalDataResponse);
}, 5500);
};

Тогда менеджер загрузок можно использовать следующим образом (в этом примере на index.js файл):

// index.js
// Require the download manager library
var DownloadManager = require("./fileDownloader");
// Create an instance of the Download Manager
var downloader = new DownloadManager();
// Add event listener of the progress of download
downloader.on("progress", function (progress){
console.log('Download progress: '+ progress +'%');
});
// Do something when the download of the file ends
downloader.on("downloadSuccess", function (response){
//{
//    filename: "imaginary.txt",
//    filesize: 123123
//}
console.log(response);
});
// Start download
downloader.downloadAsync("file.txt");

И выполнение сценария с помощью node index.js вы получите следующий вывод:

Download file "file.txt" ...
Download progress: 20%
Download progress: 40%
Download progress: 60%
Download progress: 80%
Download progress: 100%
{ filename: 'imaginary.txt',
filesize: 123123,
fileUrl: 'file.txt' }

Пример использования ECMAScript 6

Для примера в ES6 мы будем использовать ту же идею первого примера в ES5, представьте, что мы собираемся использовать библиотеку Download Manager, эта библиотека действительно проста, она предлагает способ асинхронной загрузки файла с вашего сервера , Используя класс Event Emitters файла Node.js, вы можете узнать, когда заканчивается загрузка файла, и узнать о ходе загрузки.

Пример ничего не загружает на самом деле, мы просто моделируем загрузку, используя setInterval (за progress событие) и setTimeout (за downloadSuccess событие) функция. Создать fileDownloader.js в какую-то папку вашего рабочего пространства и добавьте следующий код:

const EventEmitter = require('events');
class DownloadManager extends EventEmitter {
constructor() {
super();
}
downloadAsync(URL) {
let _this = this;
let progress = 0;
console.log(`Download file '${URL}' ...`);
// Trigger the progress event every second
let progressInterval = setInterval(() => {
progress += 20;
// Emit progress event with the progress as argument
_this.emit('progress', progress);
}, 1000);
// Trigger the downloadSuccess event in 5.5 seconds and clear the progress interval
setTimeout(() => {
let optionalDataResponse = {
filename: "imaginary.txt",
filesize: 123123,
fileUrl: URL
};
// Stop triggering progress
clearInterval(progressInterval);
// Use the emit method of the EventEmitter to trigger the downloadSuccess event !
_this.emit('downloadSuccess', optionalDataResponse);
}, 5500);
}
}
module.exports = DownloadManager

Менеджер закачек можно использовать в других файлах (index.js):

// index.js
// Require the download manager library
const DownloadManager = require('./fileDownloader');
// Create an instance of the Download Manager
const downloader = new DownloadManager();
// Add event listener of the progress of download
downloader.on("progress", (progress) => {
console.log(`Download progress ${progress}%`);
});
// Do something when the download of the file ends
downloader.on("downloadSuccess", (response) => {
//{
//    filename: "imaginary.txt",
//    filesize: 123123
//}
console.log(response);
});
// Start download
downloader.downloadAsync("file.txt");

Выполнение скрипта с использованием node index.js вы получите следующий вывод (такой же, как в примере с ES5):

Download file "file.txt" ...
Download progress: 20%
Download progress: 40%
Download progress: 60%
Download progress: 80%
Download progress: 100%
{ filename: 'imaginary.txt',
filesize: 123123,
fileUrl: 'file.txt' }

Поскольку вы используете класс EventEmitter Node.js, вы можете использовать все методы этого класса в своей библиотеке, поэтому не забудьте проверить Документы Node.js, чтобы узнать больше об Эмитентах Событий.

Ссылка на основную публикацию
Adblock
detector