async await и dispatchEvent
button.addEventListener("click", function() {
const ce = new CustomEvent(
"board:select",
{ bubbles: false, cancelable: true, detail: {} }
);
const isCancelled = !document.querySelector(`#${Board.prefix}`)?.dispatchEvent(ce);
console.log(isCancelled ? "is cancelled" : "is not cancelled");
}
//I вариант
document.querySelector(`#${Board.prefix}`)?.addEventListener("board:select", function() {
event.preventDefault();
})
//II вариант
document.querySelector(`#${Board.prefix}`)?.addEventListener("board:select", async function() {
const data = await fetch("http://localhost:4000/boards");
event.preventDefault();
})
Есть простой код, который при нажатии кнопки отсылает событие.
Вопрос - почему в первом варианте isCancelled будет true, во втором будет false.
Хотелось бы дождаться выполнения fetch и уже тогда ставить event.preventDefault(); или не ставить. Сейчас же во втором варианте event.preventDefault(); не отрабатывает.
Подскажите в чем дело?
Ответы (2 шт):
dispatchEvent выполняется синхронно, и результат возвращает сразу.
async/await делают функцию асинхронной - и в момент возврата значения функцией dispatchEvent - метод preventDefault еще не был вызван, соответственно и возвращается true
const data = await fetch("http://localhost:4000/boards"); event.preventDefault();
Поздно отменять событие, если оно уже произошло.
Хотелось бы дождаться выполнения fetch и уже тогда ставить event.preventDefault(); или не ставить.
Так сделать нельзя, потому что событие рассылается синхронно. Впрочем, в большинстве случаев клик можно повторить программно при необходимости:
var bypassClick = false
document.querySelector("a").addEventListener("click", async e => {
if (bypassClick) return
e.preventDefault()
var a = e.target.closest("a")
if (a.classList.contains("disabled")) return
a.classList.add("disabled")
try {
if (await shouldBypassClick()) {
bypassClick = true
e.target.click()
bypassClick = false
} else {
console.log("Prevented")
}
} finally {
a.classList.remove("disabled")
}
})
function shouldBypassClick() {
return new Promise(resolve => setTimeout(resolve, 1000, Math.random() > .5))
}
.disabled {
opacity: .5;
pointer-events: none;
}
<a href="data:text/plain,Link%20clicked">Click me</a>