Nodejs EventEmitter — определяет область для функции прослушивателя

#javascript #node.js #scope #eventemitter

#javascript #node.js #область действия #eventemitter

Вопрос:

Я хотел бы иметь что-то вроде этой работы:

 var Events=require('events'),
    test=new Events.EventEmitter,
    scope={
        prop:true
    };

test.on('event',function() {
   console.log(this.prop===true);//would log true
});
test.emit.call(scope,'event');
  

Но, к сожалению, прослушиватель даже не вызывается. Есть ли какой-либо способ сделать это с помощью EventEmitter? Я мог бы Function.bind обратиться к слушателю, но я действительно надеюсь, что EventEmitter есть какой-то особый (или очевидный 😉 способ сделать это…

Спасибо за помощь!

Ответ №1:

Нет, потому что this значение в прослушивателе является объектом источника события.

Однако то, что вы можете сделать, это

 var scope = {
  ...
};
scope._events = test._events;
test.emit.call(scope, ...);
  

Причина, по которой ваш обработчик событий не был вызван, заключается в том, что все обработчики хранятся в, ._events поэтому, если вы скопируете ._events , он должен работать.

Комментарии:

1. Да, теперь это кажется таким очевидным. Спасибо, что просветили :).

2. Поскольку свойство _events, созданное для объектов, расширенных из EventEmitter, не является частью его документированного общедоступного интерфейса, является ли это мудрым советом?

3. @RobRaisch Нет, но это вряд ли изменится.

4. На сегодняшний день с узлом 0.10.38, 0.12.4 и IO.JS 2.2.1, этот подход по-прежнему работает без сбоев. Проверено временем 🙂 Отличный ответ! Спасибо!

Ответ №2:

Это не сработает, и у emit есть только удобный способ передачи параметров, но нет для настройки this . Похоже, вам придется делать привязку самостоятельно. Однако вы могли бы просто передать его в качестве параметра:

 test.on('event',function(self) {
   console.log(self.prop===true);//would log true
});
test.emit('event', scope);
  

Комментарии:

1. Нравится это для простоты! Однако, если эмиссия находится не под вашим контролем, а под управлением фреймворка, это, к сожалению, не решит проблему.

2. Все свидетельствует об обратном. 4 года спустя принятый ответ все еще оказывается действительным в каждой версии Node JS: 0.10.38, 0.12.4, IO.JS 2.2.1. Работает как шарм 🙂

Ответ №3:

Я наткнулся на этот пост, когда Google искал пакет в NPM, который обрабатывает это:

 var ScopedEventEmitter = require("scoped-event-emitter"),
    myScope = {},
    emitter = new ScopedEventEmitter(myScope);

emitter.on("foo", function() {
    assert(this === myScope);
});

emitter.emit("foo");
  

Полное раскрытие, это пакет, который я написал. Мне это было нужно, чтобы я мог иметь объект со свойством EventEmitter, которое выдается для содержащего объекта. Страница пакета NPM:https://www.npmjs.org/package/scoped-event-emitter

Комментарии:

1. Принятый ответ работает отлично, нет необходимости в целой дополнительной библиотеке 🙂

2. Это называется повторным использованием кода. «Вся дополнительная библиотека» представляет собой файл Javascript из 37 строк, но поскольку это опубликованный пакет, вы можете использовать его во многих проектах, не ища тот проект, в который вы добавили принятый ответ. Кроме того, принятый ответ не существовал, когда это было опубликовано.