Перво-наперво: выполнение JS является однопоточным по своей природе. Независимо от того, насколько асинхронным кажется ваш код, в любой момент времени выполняется только одна его часть. Вы можете прочитать больше об этом здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
Во-вторых, прослушиватели событий запускаются в цикле в порядке их подключения. Вы можете думать об этом примерно так:
handlers.forEach((handler) => {
try { handler(event); } catch (e) { /* put warning in console */ }
});
Но я боюсь, что это может быть только потому, что обстоятельства допускают это. Что если fetchDataFromDatabase () занимает несколько мс "слишком долго"?
С помощью следующего теста вы можете наблюдать, как цикл while в первом слушателе событий останавливает срабатывание второго, подтверждая тем самым ваше подозрение.
Примечание: я не встраивал его как фрагмент кода, потому что переопределение консоли фрагментов каким-то образом нарушило этот пример. Просто вставьте его в консоль браузера.
// $(e).click(fn) roughly equals e.addEventListener('click', fn);
window.addEventListener('test', () => {
console.log('first handler', new Date());
const time = Date.now();
while (Date.now() - time < 2000) {}
});
window.addEventListener('test', () => {
console.log('second handler', new Date());
});
window.dispatchEvent(new Event('test'));
Однако ...
Если вы выполняете работу асинхронно, все становится намного лучше.
window.addEventListener('test', () => {
setTimeout(() => {
console.log('first handler');
}, 1000);
});
window.addEventListener('test', () => {
console.log('second handler');
});
window.dispatchEvent(new Event('test'));
В этом примере вы можете видеть, что, хотя первый обработчик событий планирует таймер, он не блокирует запуск следующих прослушивателей событий. То же самое верно, если вы скажете, сделайте запрос XHR.
Итак, наконец, , вооружившись этой информацией, мы можем сказать, что на самом деле лучше использовать один прослушиватель событий, как во втором фрагменте.