JavaScript
async-await
fetch-api
duplicate-question
programming

JavaScript skip await on pending fetch

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

You do not have to await a fetch call immediately after creating it. A fetch starts as soon as the function is invoked and returns a promise, and you can store that promise, do other work, then await it later. The important question is whether you want sequential behavior, concurrent behavior, or to intentionally ignore the result.

Starting A Fetch Without Awaiting Immediately

This is a normal and useful pattern when you want concurrency.

javascript
1async function loadPage() {
2  const userPromise = fetch("https://jsonplaceholder.typicode.com/users/1");
3  const postsPromise = fetch("https://jsonplaceholder.typicode.com/posts/1");
4
5  const userResponse = await userPromise;
6  const postsResponse = await postsPromise;
7
8  const user = await userResponse.json();
9  const post = await postsResponse.json();
10
11  console.log(user.name, post.title);
12}
13
14loadPage().catch(console.error);

Both requests start early. Awaiting later does not "skip" the fetch. It only delays when you pause for the result.

When This Is Better Than Immediate Await

Immediate sequential awaits force one network round trip to finish before the next begins.

javascript
1async function slowVersion() {
2  const user = await fetch("https://jsonplaceholder.typicode.com/users/1");
3  const post = await fetch("https://jsonplaceholder.typicode.com/posts/1");
4  console.log(user.status, post.status);
5}

This is slower when the requests are independent. Starting both first is usually better.

If You Want To Ignore A Pending Result

You can fire a fetch and choose not to await it, but then you are responsible for error handling. Otherwise rejected promises can become unhandled failures.

javascript
1function sendAnalytics() {
2  fetch("https://example.com/track", { method: "POST" })
3    .catch((err) => {
4      console.error("analytics failed", err);
5    });
6}

This pattern is fine for best-effort side effects, but it should be intentional.

Promise Storage Is Not Cancellation

Skipping await does not pause or cancel the request. The request is already in flight. If you later decide the result is no longer relevant, use AbortController.

javascript
1async function loadWithAbort() {
2  const controller = new AbortController();
3  const promise = fetch("https://jsonplaceholder.typicode.com/todos/1", {
4    signal: controller.signal,
5  });
6
7  controller.abort();
8
9  try {
10    await promise;
11  } catch (err) {
12    console.log(err.name);
13  }
14}
15
16loadWithAbort();

That is how you stop caring about a pending fetch cleanly.

Use Promise.all For Independent Work

If multiple fetches are all required, Promise.all is often clearer than storing each promise manually.

javascript
1async function loadTogether() {
2  const [userRes, postRes] = await Promise.all([
3    fetch("https://jsonplaceholder.typicode.com/users/1"),
4    fetch("https://jsonplaceholder.typicode.com/posts/1"),
5  ]);
6
7  const [user, post] = await Promise.all([
8    userRes.json(),
9    postRes.json(),
10  ]);
11
12  console.log(user.username, post.id);
13}
14
15loadTogether().catch(console.error);

This communicates that the operations are concurrent and jointly required.

UI Lifecycle Still Matters

In browser UI code, starting a fetch early is only safe if the surrounding component or page still owns the result. If the user navigates away or a newer request supersedes the old one, pair the fetch with cancellation or stale-result guards.

When You Should Await Immediately

If the next line depends on the result of the fetch, delaying the await just adds noise. Concurrency is useful only when there is independent work to do in between.

That means the best rule is simple:

  • await immediately for dependent work,
  • start first and await later for independent work,
  • do not await at all only for deliberate fire-and-forget scenarios with explicit error handling.

Common Pitfalls

  • Thinking that not awaiting immediately prevents the fetch from starting.
  • Firing a fetch and ignoring promise rejection handling.
  • Using delayed await when the result is needed immediately anyway.
  • Confusing concurrency with cancellation.
  • Starting many fetches early without backpressure or lifecycle control.

Summary

  • A fetch begins when called, not when awaited.
  • You can safely store the promise and await it later to get concurrency.
  • Use Promise.all when multiple independent fetches are all required.
  • If you truly ignore the result, handle errors explicitly.
  • Use AbortController, not delayed await, when you need cancellation.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.