Async Event Handling


#1

With more web APIs going async (and promise-based), I’m feeling more constrained by event handlers’ synchronous nature. Decisions about the default action need to be made immediately.

Take this simple example of needing to prompt for user action to confirm the submission of a form. You can exploit the fact that confirm or prompt stop the world and block before returning a result.

form.addEventListener('submit', function(event) {
  if (!confirm("Are you sure?")) {
    event.preventDefault();
  }
});

But theres no way to get this behavior if confirm was async and returned a Promise. You can’t define an application modal that could act like the system’s blocking confirm.

Related is an async waiting mechanize in the Service Worker event API.

this.addEventListener('install', function(event) {
  event.waitUntil(shellResources.ready());
});

Here, application logic can delay the default “install” action.

I thought it would be interesting if a similar API could be expose on other event types. Going back to the modal example blocking the form submit.

form.addEventListener('submit', function(event) {
  event.waitUntil(showConfirmModal("Are you sure?").then(function(result) {
    if (!result) {
      event.preventDefault();
    }
  }));
});

I think event.waitUntil has raised some criticism about its awkwardness, but it definitely exposes some useful functionality. Maybe theres a third aspect to event properties in addition to cancelable and bubbles. Event dispatch is optionally pausable.

Looking further into the future, it’d be pretty neat if await just magically worked in event handlers.

form.addEventListener('submit', function^(event) {
  var result = await showConfirmModal("Are you sure?");
  if (!result) {
    event.preventDefault();
  }
});

This glosses over the fact every event dispatch caller would than have to be async. Which I don’t see how this could be supported in a backwards compatible way. Maybe if some new observables API totally replaces events one day, they could be designed to handle async handlers better.

This isn’t meant to be a specific feature request or proposal, I was just hoping to discuss the how these async cases should be handled in event handlers. Could event.waitUntil become the convention for handling theses use cases for other event types? I’m mostly interested in implementing this type of API on custom events provide by web components.