LearningJavaScript TutorialFetch API & JSON
CHAPTER 16 · WEB APIS

JavaScript Fetch API & JSON

Real web apps ko server se data lena aur bhejna padta hai. Is chapter me fetch(), HTTP responses, JSON, GET/POST requests, errors, loading states, cancellation aur API safety ko practical examples ke saath samjhenge.

English + Hinglish50 min readPractice included

What is an API?

An API is a defined way for software systems to communicate. Browser apps commonly send HTTP requests to web APIs and receive data back.

Hinglish Explanation

Frontend ko agar courses, profile, weather ya products ka fresh data chahiye, to wo aksar server API ko request bhejta hai. Server response me data, status aur headers return karta hai.

HTTP request and response

A request includes a URL, method, headers and sometimes a body. A response includes a status code, headers and usually a body.

  • GET — data read/fetch karna.
  • POST — new data send/create karna.
  • PUT/PATCH — existing data update karna.
  • DELETE — resource delete request karna.
Important: HTTP method ka exact behavior API contract decide karta hai. Documentation read karo.

Your first fetch()

fetch() a Promise returns karta hai that resolves to a Response object when an HTTP response is received.

first-fetch.jsJS
fetch("https://api.example.com/courses")
  .then(response => {
    console.log(response.status);
    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error("Request failed", error);
  });

The Response object

The Response object contains metadata and methods for reading the body.

response.jsJS
const response = await fetch("https://api.example.com/courses");

console.log(response.ok);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers.get("content-type"));
  • ok is true for HTTP status 200–299.
  • status is the numeric HTTP status.
  • headers provides response header access.

fetch does not reject for every HTTP error

A common beginner surprise: fetch() normally rejects on network-level failure, but responses such as 404 or 500 still resolve to a Response. Check response.ok yourself.

check-status.jsJS
async function getCourses() {
  const response = await fetch("https://api.example.com/courses");

  if (!response.ok) {
    throw new Error(`HTTP ${response.status}`);
  }

  return response.json();
}

What is JSON?

JSON (JavaScript Object Notation) is a text format commonly used to exchange structured data.

course.jsonJSON
{
  "id": 16,
  "title": "Fetch API & JSON",
  "published": true,
  "topics": ["fetch", "http", "json"]
}
JSON is text: JSON syntax looks similar to JavaScript objects, but it is a data format with stricter rules.

JSON.parse() and JSON.stringify()

JSON.parse() JSON text ko JavaScript value me convert karta hai. JSON.stringify() JavaScript value ko JSON text me convert karta hai.

json.jsJS
const text = '{"name":"Aman","score":88}';
const student = JSON.parse(text);

const payload = JSON.stringify({
  name: "Riya",
  score: 92
});

console.log(student.name);
console.log(payload);

Functions, undefined and some special JavaScript values do not round-trip through JSON the same way normal data does.

response.json()

response.json() response body ko read and parse karta hai and returns a Promise.

load-json.jsJS
async function loadCourses() {
  const response = await fetch("https://api.example.com/courses");

  if (!response.ok) {
    throw new Error(`Could not load courses: ${response.status}`);
  }

  const courses = await response.json();
  return courses;
}
Body consumption: A response body is a stream and is normally consumed once. Do not expect repeated response.json() calls on the same response to work.

Fetch with async/await

dashboard.jsJS
async function showDashboard() {
  try {
    const courses = await loadCourses();
    console.log(courses);
  } catch (error) {
    console.error("Dashboard error", error);
  }
}

showDashboard();

async/await fetch ke Promise flow ko readable banata hai, but proper status checks and error handling still required hain.

Query parameters

Query parameters URL me filtering, searching or pagination values carry kar sakte hain.

query.jsJS
const params = new URLSearchParams({
  level: "beginner",
  page: "2"
});

const url = `https://api.example.com/courses?${params}`;
const response = await fetch(url);
Use URLSearchParams: Manual string concatenation se encoding mistakes ho sakti hain.

POST request with JSON

To send JSON, method, headers and body options provide karo.

post.jsJS
const newProgress = {
  courseId: 16,
  percent: 70
};

const response = await fetch("https://api.example.com/progress", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(newProgress)
});

if (!response.ok) {
  throw new Error(`Save failed: ${response.status}`);
}

Request headers

Headers request ke baare me metadata provide karte hain. Common examples include content type and authorization.

Security: Secret API keys ko public frontend JavaScript me hard-code mat karo. Browser-delivered code users inspect kar sakte hain.

Authorization basics

Some APIs require credentials or tokens. Exact mechanism API architecture par depend karta hai. Token ko sirf isliye “safe” mat samjho because variable name private lag raha hai.

Sensitive secrets usually trusted backend/server environment me belong karte hain. Frontend ko user-scoped, short-lived or otherwise intentionally public-client-safe credentials hi receive karne chahiye.

CORS

Browsers enforce origin security rules. Cross-origin requests may require the server to allow the requesting origin through CORS response headers.

Simple idea

Agar browser bole “CORS blocked”, sirf frontend code change karke har case solve nahi hota. Server ko correct CORS policy return karni pad sakti hai.

Loading, success, empty and error states

API call sirf data function nahi hai; UI ko multiple states handle karne chahiye.

ui-state.jsJS
async function loadCourseList() {
  setStatus("Loading courses...");

  try {
    const courses = await loadCourses();

    if (courses.length === 0) {
      setStatus("No courses found");
      return;
    }

    renderCourses(courses);
    setStatus("");
  } catch (error) {
    setStatus("Could not load courses. Try again.");
  }
}
Accessibility: Important async status text ko visible rakho. Where appropriate, a polite live region can announce meaningful loading/error updates without moving keyboard focus unnecessarily.

Render API data safely

API se aaya text automatically trusted HTML nahi hota. Plain text display ke liye textContent prefer karo.

render.jsJS
function renderCourse(course) {
  const item = document.createElement("li");
  item.textContent = course.title;
  return item;
}
Avoid: Untrusted API/user data ko directly innerHTML me inject mat karo.

Cancel requests with AbortController

AbortController unnecessary in-flight fetch ko cancel kar sakta hai, for example when a search query changes quickly or a view is closed.

abort.jsJS
const controller = new AbortController();

const request = fetch("https://api.example.com/courses", {
  signal: controller.signal
});

controller.abort();

try {
  await request;
} catch (error) {
  if (error.name === "AbortError") {
    console.log("Request cancelled");
  }
}

Timeout pattern

A timeout can be built by aborting a request after a chosen limit. Timeout value should reflect the product and network conditions, not an arbitrary tiny number.

timeout.jsJS
async function fetchWithTimeout(url, ms = 8000) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), ms);

  try {
    return await fetch(url, { signal: controller.signal });
  } finally {
    clearTimeout(timer);
  }
}

Useful error handling

Different failure types ko distinguish karna useful ho sakta hai: network unavailable, HTTP error, invalid JSON, cancellation or application-level error.

robust-fetch.jsJS
async function getJson(url) {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`Request failed with ${response.status}`);
  }

  return response.json();
}

User-facing message simple ho sakta hai while console/logging me technical details available rakhe ja sakte hain.

Multiple API requests

Independent required requests can run in parallel with Promise.all().

parallel-fetch.jsJS
const [profile, courses] = await Promise.all([
  getJson("https://api.example.com/profile"),
  getJson("https://api.example.com/courses")
]);

If partial success is acceptable, Promise.allSettled() may fit better.

Retries: use carefully

Automatic retries can help some temporary GET failures, but blindly retrying every request can duplicate writes or overload a struggling service.

Rule: Retry policy should consider method idempotency, server guidance, backoff and user experience.

Debug API requests in DevTools

Browser DevTools Network panel me request URL, method, status, request/response headers, timing and response body inspect karo.

  • Was the request actually sent?
  • Correct URL and method?
  • Status code kya hai?
  • Response content type expected hai?
  • Payload/body correct format me hai?
  • CORS or network error console me hai?

Common beginner mistakes

  • response.ok check na karna.
  • response.json() ko non-Promise value samajhna.
  • JSON.parse() aur response.json() ko same context me confuse karna.
  • POST JSON body par JSON.stringify() bhoolna.
  • Wrong Content-Type header send karna.
  • Secret API key frontend code me expose karna.
  • CORS error ko sirf fetch syntax problem samajhna.
  • Loading/error/empty UI states ignore karna.
  • Untrusted API text ko innerHTML se render karna.
  • Search typing par stale requests ko ignore na karna.

Beginner best practices

  • Small reusable getJson()-style helpers banao where useful.
  • HTTP status explicitly check karo.
  • Expected response shape validate/guard karo before deeply using values.
  • UI me loading, success, empty and failure states plan karo.
  • Plain text ke liye textContent use karo.
  • Secrets ko frontend bundle me store mat karo.
  • Independent requests ko parallelize only when appropriate.
  • Abort stale requests when it improves correctness or UX.
  • Network panel se real request/response inspect karo.

Chapter checklist

  • fetch() se GET request kar sakte ho?
  • Response, status aur ok samajh aaye?
  • response.json(), JSON.parse() aur JSON.stringify() ka difference clear hai?
  • HTTP 404/500 ko explicitly error flow me handle kar sakte ho?
  • POST JSON request bana sakte ho?
  • CORS ka browser-level purpose samajh aaya?
  • Loading/error/empty UI states plan kar sakte ho?
  • AbortController ka basic use clear hai?

Practice Task — Course API Viewer

Ek small browser page banao jo API data load karke safely render kare.

  1. loadCourses() async function banao.
  2. fetch() se course endpoint request karo.
  3. response.ok check karo.
  4. Response ko response.json() se parse karo.
  5. Loading text show karo.
  6. Empty array ke liye “No courses found” state show karo.
  7. Error case me friendly message show karo.
  8. Course titles ko textContent se list me render karo.
  9. Query filter ke liye URLSearchParams use karo.
  10. Ek POST request ka sample function banao with JSON body.
  11. JSON.stringify() ka output console me inspect karo.
  12. AbortController se previous search request cancel karne ka pattern test karo.
  13. DevTools Network panel me status, headers, payload and timing inspect karo.
  14. Finally intentionally bad URL use karke error UI verify karo.