Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

How can I call an async function from an event handler and surface its errors?

Quick answer

Make the handler async, handle the awaited work with try/catch, and use finally to restore the busy state whether the work succeeds or fails. Put event-specific decisions—such as whether to prevent a form’s normal submission—at the start of the handler, separately from the request. Show progress and a useful error in the interface; don’t leave a rejected operation with no visible outcome. [S1] [S2]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

What’s the basic pattern? I have a form submit handler that calls an async save function, and I want the user to see both loading and errors.

Geez

Keep the event decision, request, and UI cleanup as distinct steps. For a form, decide at the start whether its ordinary submission should be prevented. Then mark the interface busy, await the save, show success or an error, and restore the control in finally.

form.addEventListener("submit", async (event) => {
  event.preventDefault(); // Use if this handler replaces normal form submission.
  submitButton.disabled = true;
  status.textContent = "Saving…";

  try {
    await saveForm();
    status.textContent = "Saved.";
  } catch (error) {
    status.textContent = "Could not save. Please try again.";
    console.error("Save failed:", error);
  } finally {
    submitButton.disabled = false;
  }
});

Replace saveForm, form, submitButton, and status with your own function and elements. Promise catch() handles a rejection, while finally() runs after either fulfillment or rejection; an awaited operation can also be handled with try/catch/finally. [S1] [S2] The references establish those JavaScript handling and cleanup patterns, not the behavior of DOM events or a particular interface. The preventDefault() line is an event-specific choice: keep it if this handler should take over submission, and omit it if you want the form’s usual submission behavior.

Follow-up question

Why set the busy state before the try, and what if the save fails?

Geez

Set the busy state immediately before starting the awaited work so the interface reflects the operation as soon as the handler reaches it. In this example, the status first says “Saving…” and the button is disabled; if saveForm() rejects, control moves to catch, where the status becomes a visible, user-friendly error. The finally block then restores the button on either outcome. [S2]

Keep the on-screen message useful without exposing internal details. If a failure needs investigation, logging the error can help during development, but don’t assume that a generic message tells the user whether the data was saved. That depends on what your save operation can establish.

Follow-up question

Should I put preventDefault() inside the try block? And does making the listener async take care of errors on its own?

Geez

Put the event decision at the beginning, before the asynchronous work, so it is visibly separate from success and failure handling. Use preventDefault() only when you intend this handler to replace the form’s ordinary submission; it is not an error-handling step. The supplied JavaScript references explain promise rejection handling and cleanup, but do not establish DOM event behavior, so confirm the event behavior you need in documentation for your environment.

Treat async as a way to write code that awaits work, not as a user-facing error message. Put the awaited operation inside the try and give catch an explicit response. The references support using try/catch for awaited failures and finally for cleanup. [S1] [S2]

Follow-up question

Can you give me a reusable checklist and a copyable version with clearly named placeholders?

Geez

The first example is the copyable version. Replace its placeholders with your own elements and operation: form is the form, submitButton is the control to disable, status is the visible message area, and saveForm() is the asynchronous work. Keep event.preventDefault() only if this handler should replace the form’s normal submission.

As you adapt it, check that you:

  • show a busy state before awaiting the operation;
  • provide an explicit success or failure message;
  • use finally to restore the control after either outcome.

Choose a success message only when the awaited work completes successfully. Use catch for the rejection response and finally for cleanup. [S1] [S2]

A practical checklist

  • Decide whether the handler should prevent the event’s ordinary behavior; keep that decision separate from the request.

  • Show a busy state before awaiting the operation.

  • Handle the awaited operation’s rejection with catch or try/catch.

  • Give the user a clear success or failure status without claiming more than the operation confirms.

  • Restore the control in finally so cleanup occurs after success or failure.

A few more useful answers

Should I use `.catch()` or `try`/`catch`?

Either can handle a promise rejection. For an async event handler with awaited work and cleanup, try/catch/finally keeps those steps together; the JavaScript references describe both promise catch() and the try statement’s cleanup behavior. [S1] [S2]

What should the error message say?

Use a brief message that tells the user the operation did not complete and what reasonable next step to take. Avoid reporting success or claiming the data’s state unless the operation confirms it.

Does `finally` mean the operation succeeded?

No. It runs after either fulfillment or rejection, so use it for cleanup such as restoring the busy control—not for a success message. [S1] [S2]

Sources

References used for this guide.

  1. [S1] JavaScript Promise reference: handling rejected promises
    learn.microsoft.com · Checked
  2. [S2] JavaScript try...catch: exception handling and cleanup
    learn.microsoft.com · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work