Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP W3.CSS C C++ C# HOW TO BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SWIFT SASS VUE GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING INTRO TO HTML & CSS BASH RUST TOOLS

JS Tutorial

JS Home JS Introduction JS Where To JS Output JS Syntax JS Operators JS If Conditions JS Loops JS Strings JS Numbers JS Functions JS Timers JS Objects JS Scope JS Dates JS Temporal  New JS Arrays JS Sets JS Maps JS Iterations JS Math JS RegExp JS Data Types JS Errors JS Debugging JS Style Guide JS Reference JS Projects  New JS Versions JS HTML DOM JS HTML Events JS HTML First

JS Advanced

JS Functions JS Objects JS Classes JS JSON JS Asynchronous JS Modules JS Meta & Proxy JS Typed Arrays JS DOM Navigation JS Browser API JS Web API JS Graphics

Old Technologies

JS AJAX JS jQuery JS JSONP

JS Examples

JS Examples

Debugging Async JavaScript

Asynchronous Bugs

Asynchronous code can be more difficult to debug than synchronous code.

The code often executes later than expected, and several asynchronous operations may run at the same time.

This chapter shows techniques for finding and fixing common problems in asynchronous JavaScript.

This chapter shows practical ways to debug fetch(), promises, and async/await.

Async debugging is about finding where the code stops.

Then to find why it stopped.


Log Events

The easiest way to debug asynchronous code is to log when things happen.

Use console.log()

console.log("Before fetch");

const promise = fetch("fetch.txt");

console.log("After fetch");
Try it Yourself »

Use a display function

myDisplayer("Before fetch");

const promise = fetch("fetch.txt");

myDisplayer("After fetch");
Try it Yourself »

Note

console.log(), often display the current state of a Promise like:

  • <pending>
  • <fulfilled>
  • <rejected>

This information is provided by the debugging tool. It is not part of the JavaScript language.

Why can't JavaScript do the same?

There is no standard properties like:

  • promise.state
  • promise.status

They simply do not exist.

The state part of the Promise is not in its public API.


Async Bugs Can be Invisible

Async code often fails after your function has already returned.

This makes it feel like nothing happened.

Example

// Async function to download a file
async function loadText(file) {
  const response = await fetch(file);
  myDisplayer(response);
}

myDisplayer("Start");

// Try to load a missing file
loadText("missing.txt");

myDisplayer("Done");
Try it Yourself »

The Done message prints even if loadText() fails.

This is because the fetch() fails later.


Rule 1: Always Handle Errors

Unhandled promise rejections confuse beginners.

Handle errors early and clearly.

Use try...catch to handle Promises.

Example

// Async function to download a file
async function loadData(file) {
  try {
    let response = await fetch(file);
    let data = await response.json()
    myDisplayer(JSON.stringify(data));
  } catch (error) {
    myDisplayer(error);
  }
}

// Call async function
loadData("customer.json")
Try it Yourself »

Note

The code above catches network errors and JSON parsing errors.

It does not catch HTTP errors like 404 (file not found).


Rule 2: Check response.ok

Fetch does not reject on HTTP errors like 404.

You must check response.ok.

Example

// Async function to download a file
async function loadData(file) {
  try {
    let response = await fetch(file);

    if (!response.ok) {
      console.log("HTTP Error:", response.status);
      return;
    }

    let data = await response.json()
    myDisplayer(JSON.stringify(data));
  } catch (error) {
    myDisplayer(error);
  }
}
Try it Yourself »

The code above separates HTTP errors from network errors.

Most fetch bugs are not JavaScript bugs.

They are URL and server response bugs.



Rule 3: Log the Right Things

Logging a promise is not the same as logging the data.

Log the response and status first.

Example

// Async function to download a file
async function loadData(file) {
  let response = await fetch(file);
  myDisplayer(response.status);
  myDisplayer(response.headers.get("content-type"));
}
Try it Yourself »

The above code tells you if the server returned what you expected.


Common Response Headers

HeaderDescription
Content-TypeType of the response (text/html, application/json, etc.)
Content-LengthSize of the response in bytes
Cache-ControlHow the response may be cached
ExpiresWhen the cached response expires
Last-ModifiedWhen the resource was last modified
ETagResource version identifier used for caching
DateTime the server generated the response
ServerInformation about the web server
Access-Control-Allow-OriginCORS policy
Content-EncodingCompression used (gzip, br, etc.)

Use the Browser Network Tab

The Network tab is a panel in your Browser's Developer Tools.

It shows all network request made by your web page.

It is one of the most useful tools for debugging asynchronous JavaScript because it lets you see exactly what is happening when your code uses fetch(), loads images, downloads JSON, or sends data to a server.

How to Use the Developer Tools:

  • Open a Website
  • Press F12, or
  • Right-click the page and select Inspect.
  • Then select the Network tab.
  • Refresh the page

The Network tab shows every request made by your application:

  • Which files were requested
  • Whether they succeeded
  • HTTP status codes
  • Download times

Example

Suppose your code is:

const response = await fetch("customer.json");

Some Possible Results

NameStatusTypeSizeTime
customer.json200fetch548 Bytes134ms
customer.json404fetch
customer.jsonFailed

This is much easier than trying to guess why fetch() failed.


Use Breakpoints

Modern browsers allow you to pause JavaScript execution.

While execution is paused, you can inspect variables, Promises, and the Call Stack.


Example

const response = await fetch("demo.txt");

debugger;

const text = await response.text();

When execution reaches debugger, DevTools pauses automatically.

Breakpoints on await

You can set breakpoints on await lines.

This lets you inspect values before and after async steps.

Example

async function loadData() {
  let response = await fetch("data.json");
  let data = await response.json();
  console.log(data);
}

Set a breakpoint on the first await line.

Step over and inspect response.


Common Async Errors

Forgetting await is the most common beginner mistake.

Example

async function loadData() {
  let response = await fetch("data.json");
  let data = response.json();
  console.log(data);
}

This logs a promise, not the JSON.

Example

async function loadData() {
  let response = await fetch("data.json");
  let data = await response.json();
  console.log(data);
}

Debugging Promise Chains

Promises can fail anywhere in the chain.

Add logs between steps to find where it fails.

Example

fetch("data.json")
.then(function(response) {
  console.log("Got response");
  return response.json();
})
.then(function(data) {
  console.log("Got data");
  console.log(data);
})
.catch(function(error) {
  console.log("Failed");
  console.log(error);
});

This shows which step is failing.


Understand Execution Order

Example

myDisplayer("Start");

setTimeout(function() {myDisplayer("Timer")},1000);

myDisplayer("End");

Result

Start
End
Timer
Try it Yourself »

Debug Parallel Operations

Result

const customer = fetch("customer.json");
const products = fetch("products.json");
const news = fetch("news.json");
  • All three requests start immediately
  • The browser may finish them in any order
  • That is normal

Check response.ok

Many beginners forget this.

Wrong:

const response = await fetch("missing.txt");

const text = await response.text();

Better:

if (!response.ok) {
  console.log(response.status);
}

Handle Promise Rejections

Example

fetch("missing.txt")
.then(function(response){
  return response.text();
})
.catch(function(err){
  console.log(err);

});

Explain the difference between:

  • Rejected Promise
  • HTTP error

Use finally()

Example

showSpinner();
try {
  ...
}
finally {
  hideSpinner();
}

Cleanup code belongs in finally().


Debugging HowTo

  • Add try...catch around awaited code.
  • Check both response.ok and response.status.
  • Use breakpoints on await lines.
  • Use the Network tab.

Debugging Checklist

  • Did the Promise resolve?
  • Did you forget await?
  • Did you check response.ok?
  • Is your code inside an async function?
  • Did the request appear in the Network tab?
  • Are errors reported in the Console?
  • Are you blocking the Event Loop?

Summary

  • Use console.log() to trace execution.
  • Inspect Promise objects while debugging.
  • Use try...catch to handle rejected Promises.
  • Use the browser's Network tab to inspect requests.
  • Set breakpoints to inspect variables and execution.
  • Check response.ok after every fetch().


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookies and privacy policy.

Copyright 1999-2026 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.

-->