2015-06-28 5 views
0

При создании внутреннего EventEmitter для моего проекта мне стало любопытно, как создать конкретное поведение итерации цикла для подключенных обработчиков событий. Вот демонстрация моего беспокойства:Создание определенного поведения цикла

MyEventEmitter.prototype.emit = function (name, event) { 
    var index; 

    if (name in this.events) { 
     for (index = 0; index < this.events[name].length; index++) { 
      this.events[name][index].call(this, event); 
     } 
    } 
}; 

Чтобы уточнить, this.events является объектом с каждым ключом является именем события и каждое значение является массивом обработчиков событий вызываются для соответствующего события.

Однако, как я наблюдал с Unexpected behavior of Array.prototype.splice, этим сбоем будет для обработчиков событий с приложением MyEventEmitter.prototype.once, так как функция обертки обработчиков события будет удалить себя, в результате чего итерации, чтобы пропустить обработчик событий в пределах индексов массива сразу же после того, как одно- обработчиков событий в массиве. Вот что я имею в виду:

var array = [1, 2, 3, 4, 5], index; 

for (index = 0; index < array.length; index++) { 
    // log event handlers that get called 
    console.log(array[index]); 
    // let's assume that `3` is like an event handler that removes itself 
    if (array[index] === 3) { 
     array.splice(index, 1); 
    } 
} 

Этот журнал будет следующее:

1 
2 
3 
5 

Обратите внимание, что 4 не получает, потому что итерация 3 удаляет себя. Как мне написать emit, чтобы разместить это? Или, если это уместно, как это делают внутренние реализации EventEmitter?

+0

@jooko спасибо, забыли добавить этот тег –

ответ

0

Посмотрев на источник узла себя, я обнаружил their solution in events.js:

listeners = handler.slice(); 

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

Смежные вопросы