Skip to main content

await in an event handler

1. The basic rule

await can only be used inside a function declared with async. This means that if the event handler is a regular function, await inside it will cause an error:

javascript
button.addEventListener('click', () => { await fetch('/api/data'); // SyntaxError });

For this to work, the handler needs to be declared as async:

javascript
button.addEventListener('click', async () => { const response = await fetch('/api/data'); const data = await response.json(); console.log(data); });

Now it's all legal - the browser will wait for fetch inside the handler, but the event itself does not "freeze" the UI: the rest of the code keeps running.


2. Example of using await in a handler

javascript
<button id="load">Load data</button> <div id="result"></div> <script> const btn = document.querySelector('#load'); const result = document.querySelector('#result'); btn.addEventListener('click', async () => { result.textContent = 'Loading...'; try { const res = await fetch('https://jsonplaceholder.typicode.com/posts/1'); const post = await res.json(); result.textContent = post.title; } catch (err) { result.textContent = 'Failed to load'; } }); </script>

What happens:

  • on click, the async handler starts;
  • await fetch(...) pauses execution inside the function;
  • once the data loads, it is displayed;
  • meanwhile the interface is not blocked (JS stays asynchronous).

3. You can also declare a separate async function

Sometimes it's more convenient to move the logic out:

javascript
async function handleClick() { const data = await fetchData(); render(data); } button.addEventListener('click', handleClick);

It works exactly the same way.


4. Important to remember

  • Event handlers do not wait for the result of await. That is, addEventListener does not know that there's an await inside the handler. Code outside the handler keeps running right after the call.

  • Errors inside an async handler need to be caught with try/catch, otherwise they go into the Promise and can go unnoticed:

    javascript
    btn.addEventListener('click', async () => { try { await riskyOperation(); } catch (e) { console.error('Error:', e); } });
  • event.preventDefault() and stopPropagation() work immediately, regardless of await - they can be called before the asynchronous operations.


Summary

QuestionAnswer
Can await be used in a handler?Yes, if it is async
Can await be declared without async?No
Does it block the interface?No
Do errors need to be caught?Yes, via try/catch
Can the async function be moved out separately?Yes, the better style

A simple way to remember it: await inside a handler is fine, as long as the handler is async, and errors are handled.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.