0

I'm having a trouble wrapping my head around this problem: suppose I have a form where I want to handle onSubmit using async callback through event listener and I want to prevent the default behavior. I don't understand why this works:

form.addEventListener('submit', async(event) => {
// do stuff
event.preventDefault();
await asyncFetching(); // first await
// do more stuff
}

And this doesn't:

form.addEventListener('submit', async(event) => {
// do stuff
await asyncFetching(); // first await
event.preventDefault();
// do more stuff
}

I've come to understand from event.preventDefault in async functions that event will have happened by the time await unblocks. But I don't get it. This is what I expect:

  1. Event is triggered once we click the button
  2. Event handler fires up
  3. Event handler finishes execution
  4. Event has happened

What am I missing here?

RomanM
  • 93
  • 2
  • 6
  • the event handler doesn't **wait** on the callbacks you give it, therefore after simply calling your *callback*, it would decide if to do default activity or not. In the first example, after running, the event handler was already told to prevent default, whereas the second example is still busy with `asyncFetching()` – The Bomb Squad Nov 09 '22 at 20:34

1 Answers1

1

After some time experimenting and reading up further I think I get it now.

From MDN:

The body of an async function can be thought of as being split by zero or more await expressions. Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

Inside the event handler everything is executed synchronously. Once first await is reached, it is the same as returning a Promise in pending state that has just executed asyncFetching() and has event.preventDefault() inside of its then() block. This return indeed signals that event handler callback has finished its execution, so by the time when asyncFetching() fails or succeeds, event.preventDefault() will still execute, but it won't have any effect because its eventPhase will be 0 meaning Event.NONE ("No event is being processed at this time").

RomanM
  • 93
  • 2
  • 6