Слушатель событий Hashchange прослушивает до того, как обработчик события будет присоединен к событию

У меня есть следующий код

console.info('checking if url contains hash');
if (!location.hash) {
  console.warn('if-block replacing hash to empty!');
  location.href = '#';

  // Running route() to trigger Router.otherwise()
  console.info('running route() from if-block(hash doesn\'t exist)');
  route(location.hash.slice(1));
} else {
  // URL contains a hash. Running Router.when() to load template
  console.info('running route() from else-block(hash already present in url)');
  route(location.hash.slice(1));
}

// Bind hashchange-event to window-object... duh
console.info('binding hashchange event');
$(window).on('hashchange', function () {
  console.info('running route() from hashchange');
  route(location.hash.slice(1));
});

Ясно, что прослушиватель событий присоединен после блока else-if. Вывод моей консоли подтверждает это

2015-02-13 12:51:14.281 main.js:69 checking if url contains hash
2015-02-13 12:51:14.284 main.js:71 if-block replacing hash to empty!
2015-02-13 12:51:14.290 main.js:75 running route() from if-block(hash doesn\'t exist)
2015-02-13 12:51:16.677 main.js:84 binding hashchange event
2015-02-13 12:51:16.678 main.js:86 running route() from hashchange

Похоже, что прослушиватель событий каким-то образом улавливает ранее инициированное событие hashchange.
Это происходит только в том случае, если URL имеет значение example.com, а не example.com/#. Если / или /# отсутствуют в URL-адресе при входе на сайт, возникает это явление.

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

Другое редактирование: еще более наглядный пример, показывающий, что когда я впервые запускаю getEventListeners(window), к событию hashchange не подключаются слушатели. Несмотря на это, когда я добавляю прослушиватель событий, он получает ранее запущенный hashchange console logs

Я что-то упустил или что происходит?
Есть ли способ обойти это?


person mhrvatin    schedule 13.02.2015    source источник
comment
Обойти что? Ничто из того, что показано, не указывает на преждевременное срабатывание события. Пожалуйста, объясните проблему более подробно. вообще не понятно чего ждать   -  person charlietfl    schedule 13.02.2015
comment
@charlietfl я добавил пояснение к своему OP   -  person mhrvatin    schedule 13.02.2015
comment
что заставляет вас говорить, что это срабатывает преждевременно? Ваше изменение является заявлением, которое не поддерживается тем, что показано в журналах консоли. Демонстрация, которая воспроизводит проблему, может помочь.   -  person charlietfl    schedule 13.02.2015
comment
@charlietfl в журналах консоли указано, что в строке 69 мой блок if-else начинает работать, и к URL-адресу добавляется хэш, что вызывает событие hashchange. Но я еще не прикрепил прослушиватель событий к hashchange, что видно в строке 84 в журналах консоли.   -  person mhrvatin    schedule 13.02.2015
comment
тогда вам нужно показать больше кода, то, как код отображается, журналы правильные   -  person charlietfl    schedule 13.02.2015
comment
@charlietfl как правильно? Я не привязывал прослушиватель событий к hashchange при изменении хэша. Тем не менее, когда я добавляю прослушиватель, он срабатывает сразу же, поскольку я изменил хэш до его добавления. Не могли бы вы объяснить это в ответ? Я посмотрю, смогу ли я воспроизвести проблему на скрипке.   -  person mhrvatin    schedule 13.02.2015
comment
некоторые из ваших журналов не имеют ничего общего с событием   -  person charlietfl    schedule 13.02.2015
comment
@charlietfl добавил изображение с большим количеством журналов. Не могли бы вы помочь, если вы знаете, что происходит, вместо того, чтобы просто сказать, что все в порядке?   -  person mhrvatin    schedule 13.02.2015


Ответы (1)


Давайте упростим ваш код до

location.hash = 'foobar';
window.onhashchange = function() {
  document.body.innerHTML = 'You should not see me. But you do :(';
};

Чтобы решить эту проблему, вы можете использовать setTimeout для задержки добавление обработчика события:

location.hash = 'foobar';
setTimeout(function(){ // Delayed code
  window.onhashchange = function() {
    document.body.innerHTML = 'You should not see me. And you do not :)';
  };
}, 0);

person Oriol    schedule 13.02.2015
comment
Я понимаю, что могу использовать это как обходной путь. Но почему проблема возникает в первую очередь? - person mhrvatin; 13.02.2015
comment
@rymdsylt Не уверен, может быть, он обновляется асинхронно. Вы можете увидеть шаги установки hash в спецификации URL, но Я недостаточно знаю эту спецификацию, чтобы увидеть, где это происходит. - person Oriol; 13.02.2015
comment
Что ж, поскольку ваш пример помог мне решить эту проблему, я отмечаю ее как решенную. Спасибо чувак! - person mhrvatin; 14.02.2015