Новачок node.js, яка перевага, отримана за допомогою зворотних дзвінків над подіями?


24

Я початківець JavaScripter і не маю реальних знань, що відбувається всередині двигуна V8.

Сказавши це, я дуже насолоджуюся своїми ранніми переглядами в середовищі node.js, але виявляю, що я постійно використовую події.EventEmitter () як засіб випромінювати глобальні події, щоб я міг структурувати свої програми так, щоб підходити до спостерігача-сповіщувача. Шаблон, подібний до того, що я б написав у програмі Objective-C або Python.

Я вважаю, що завжди роблю такі речі:

var events = require('events');

var eventCenter = new events.EventEmitter();

eventCenter.on('init', function() {
    var greeting = 'Hello World!';
    console.log('We're in the init function!);
    eventCenter.emit('secondFunction', greeting);
});

eventCenter.on('secondFunction', function(greeting) {
        console.log('We're in the second function!);
        console.log(greeting);
    eventCenter.emit('nextFunction');
});

eventCenter.on('nextFunction', function {
    /* do stuff */
});

eventCenter.emit('init');

Тож по суті я просто структурую код "async" node.js в код, який робить речі в тому порядку, який я очікував, натомість я наче "кодую назад", якщо це має сенс. Чи буде якась різниця робити це у важкому зворотному режимі, або з точки зору продуктивності, або з філософією? Чи краще робити те ж саме, використовуючи зворотні дзвінки замість подій?


Якщо ви виявите, що читання вашого коду страждає через велике використання зворотних дзвінків, подумайте про використання рамки для завершення використання зворотних дзвінків. Це потребує трохи коригування, але обіцянки часто можуть усунути негарні зворотні дзвінки. Якщо ви використовуєте JQuery, ви можете використовувати Deferred . Однією з найпростіших рамок обіцянок є RSVP .
Брайан

Я розгублений, я не бачу нічого асинхронічного у вашому коді, просто функціональні дзвінки, написані надскладним способом.
svick

Відповіді:


27

Приємна річ у зворотному звороті - це те, що там немає глобального стану, а передача параметрів їм тривіальна. Якщо у вас є функція, download(URL, callback: (FileData)->void)то ви можете знати, що це автономна функція вищого порядку, яка по суті дозволяє побудувати функцію "схопити це і зробити це". Ви можете бути впевнені, що ваш потік коду точно такий, як ви очікували, тому що ніхто інший навіть не має обробку для цього зворотного дзвінка, і цей зворотний виклик не знає ні про що, крім заданих параметрів батьківської функції. Це робить його модульним і легким для тестування.

Якщо ви хочете зараз завантажувати 5 файлів паралельно і робити різні речі, вам потрібно виключити лише п’ять цих функцій за допомогою відповідних функцій зворотного виклику. У мові з хорошим синтаксисом анонімних функцій це може бути неймовірно потужним.

Події, з іншого боку, більше розроблені для сповіщення 1..*користувачів про певні зміни у стані. Якщо в кінці download(URL)запуску події "Завершити завершення" , яка запускає, processDownload()яка знає, де знайти дані, ви прив'язуєте ваші реалізації речей до більшої кількості стану. Як ви паралельно завантажуєте зараз? Як по-різному обробляти різні завантаження? Є download(URL, eventId)елегантний? Є downloadAndDoThing(URL)елегантний? Навряд чи.

Звичайно, як і у всьому, ти робиш компроміси. Вкладені функції зворотного виклику може зробити замовлення виконання коду більш заплутаною, і відсутність легкої глобальної робить Як добиратися поганий вибір для чого , де ви робите є 1..*відносини між виробником і споживачем. У вас складніше передати дані навколо, але якщо ви можете піти, не маючи додаткового стану, то це, як правило, користь.

Незалежно. Ви кодуєте в node.js, де зворотні виклики ідіоматичні, а мова та бібліотеки створені навколо їх використання. Незалежно від того, чи бачите ви переваги в тій чи іншій конструкції, я вважаю, що майже завжди правдою є те, що написання ідіоматичного коду будь-якою мовою матиме набагато більшу підтримку та зробить ваше життя набагато простішим, ніж намагатися його обійти.


2

Я ніколи не використовував події в NodeJS, але в цілому те, для чого я використовую події JS clientide, - це сигналізація про те, що щось сталося, наприклад, AppointmentBookedEvent, щоб різні частини представлення SPA могли реагувати на це (показувати це на часовій шкалі, завантажувати його на панелі тощо).
Але використання подій для сигналізації про завершений метод може бути небезпечною дорогою для подорожі. Ви не можете розраховувати на те, що події надходять у тому ж порядку, коли вони були звільнені, так що це може призвести до різного роду випадковостей ...
У використанні подій немає нічого поганого, але є певний рівень деталізації, на який ви не повинні проходити ; якщо ви будете дотримуватися подій, пов’язаних із доменом, це добре. Але повідомлення про те, що методи закінчені, є надто детальним.


0

Щось, що ви можете вивчити, це використання подій поза об'єктом, який їх випромінює. У вашому прикладі, як eventCenterвидається, і випускають, і обробляють власні події. Подумайте, як може змінюватися структура вашої програми, якщо інші об'єкти почнуть обробляти події.

Отже, eventCenterможе випромінювати "init", який інші об'єкти могли б потім обробити, щоб зробити свій стартовий код тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.