Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

How can I add a delay between asynchronous attempts without blocking the page?

Quick answer

Wrap setTimeout() in a promise, then await that promise between attempts inside an async function. The function pauses at await, but JavaScript does not synchronously wait there, so other work can proceed. Use a bounded loop, place the delay only between attempts, and remember that a timer may run later than its requested delay. [S1][S2]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

What is the simplest way to wait between asynchronous attempts without freezing the page?

Geez

Create a promise that resolves from a timer, then await it in the function that runs your attempts:

const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));

For example, await wait(500) pauses the progress of the current async function for about the requested delay. It does not synchronously block JavaScript while waiting: the timer is scheduled, and other JavaScript work can proceed. [S1][S2]

This distinction matters: await pauses this function, not the whole page. The timer does not guarantee that the next step will run at an exact time; it can run later than requested. [S2]

Follow-up question

How do I use that in a small sequence without accidentally making an endless retry loop?

Geez

Set a fixed maximum number of attempts, and wait only when another attempt remains. Here is a reusable pattern. performAttempt is a placeholder for your own asynchronous operation; this example treats its result as true for success and false for an unsuccessful attempt.

const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function trySeveralTimes(maxAttempts, delayMs) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const succeeded = await performAttempt(attempt); // Replace this placeholder.

    if (succeeded) return true;
    if (attempt < maxAttempts) await wait(delayMs);
  }

  return false;
}

For a concrete timing illustration, call trySeveralTimes(3, 500): it makes at most three attempts and, if needed, waits between attempt 1 and 2 and between 2 and 3. It does not add a delay after the final unsuccessful attempt. The total elapsed time is not guaranteed to equal exactly one second, because each attempt takes time and timers can run late. [S1][S2]

Follow-up question

Does awaiting the timer make the browser unresponsive, and does it guarantee the next attempt starts on schedule?

Geez

No: await suspends the async function’s progress while allowing other JavaScript work to proceed, rather than synchronously waiting and blocking execution. [S1][S2] That is different from a synchronous busy-wait loop, which keeps JavaScript occupied instead of yielding at an awaitable timer.

But it does not guarantee an exact start time. setTimeout() schedules work to run after a delay and returns immediately; the elapsed time may be longer than requested. [S2] Treat delayMs as a requested pause between attempts, not a precise clock or a guarantee that an operation will finish within a deadline. This pattern also cannot make a synchronous, long-running performAttempt non-blocking: the timer yields during the wait, not while synchronous code is running.

Follow-up question

What should I check when adapting this to my own code?

Geez

First decide what counts as a successful attempt and what the function should return if all attempts fail. Then choose an explicit maximum attempt count and a delay suited to your task. Keep the timer between attempts—not before the first one or after the last one—and make sure the operation you call is asynchronous if you expect to await its result without holding up the current function.

The snippet leaves performAttempt undefined on purpose: replace it with your own function and decide how its errors should be handled. The timer example does not determine a retry policy or what counts as success. The reusable pattern is simply: attempt, check the result, wait if another attempt is allowed, and stop at the bound.

A practical checklist

  • Wrap setTimeout() in a promise and await it from an async function.

  • Choose a finite maximum number of attempts.

  • Place the wait between attempts, skipping it after the final attempt.

  • Define what success, failure, and thrown errors mean for your operation.

  • Treat the requested timer delay as approximate, not an exact schedule.

A few more useful answers

Should I wait after the last attempt?

Usually not if the sequence is ending. Check whether another attempt remains before awaiting the delay, as in the example.

Does this make a synchronous operation non-blocking?

No. The timer wait yields while it is pending, but synchronous code in an attempt still runs synchronously.

Sources

References used for this guide.

  1. [S1] Using promises — JavaScript | MDN
    developer.mozilla.org · Checked
  2. [S2] Window: setTimeout() method — Web APIs | MDN
    developer.mozilla.org · 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