← Back to JavaScript Course | Chapter 9: Async & Web APIs | Lesson 17 of 26

JS AJAX Database

A large share of AJAX requests exist specifically to read from or write to a database -- fetching a live product list, saving a new comment, updating a status -- with JavaScript on the client sending the request and a server-side script running the actual database query and returning the result.

Fetching Database Data via AJAX

A read-only AJAX endpoint runs a database query and returns matching rows as JSON -- the JavaScript side simply fetches and parses that JSON, with no awareness of SQL, tables, or the database engine involved at all.

Note: Keep the client-side JavaScript entirely focused on requesting and rendering data, letting the server own every detail of how that data is actually stored and queried.
Warning: Returning every column from a database table, including ones never used on the client (or worse, sensitive ones), is a common accidental data leak in database-backed AJAX endpoints.

उदाहरण: Fetching Database Data via AJAX

javascript
fetch("get-users.php")
  .then(response => response.json())
  .then(rows => console.log(rows)); // JS just parses JSON, no SQL knowledge needed

Saving Data to a Database via AJAX

A write AJAX endpoint reads submitted data, validates it, and inserts or updates it in a database using a prepared statement on the server side -- the JavaScript side sends the request and reads back a confirmation, without any direct knowledge of the database operation that happened.

Note: Design the JSON response from a save endpoint to confirm what actually happened (like returning the new record's ID), giving the JavaScript enough information to update the UI accurately.
Warning: A save endpoint that returns only a generic "success" with no useful data (like the new record's ID) forces the client to make an extra request just to find out what was created.

उदाहरण: Saving Data to a Database via AJAX

javascript
// Send a POST request with a JSON body to save-user.php
fetch("save-user.php", {
  method: "POST",
  headers: { "Content-Type": "application/json" }, // tell the server we're sending JSON
  body: JSON.stringify({ name: "Sam" }), // convert the JS object into a JSON string
}).then(r => r.json()).then(confirmation => console.log(confirmation)); // parse and log the server's JSON reply

Server-Side Filtering, Sorting, and Pagination

For any dataset large enough to matter, filtering, sorting, and pagination should happen in the server's database query, not by fetching every row and processing it in JavaScript -- the client sends its desired filters as query parameters, and the server's SQL WHERE/ORDER BY/LIMIT does the actual work.

Note: Pass filter, sort, and page parameters as query parameters in the AJAX request, letting the server's database query handle them directly rather than filtering a full dataset client-side.
Warning: Fetching an entire table via AJAX and filtering it in JavaScript works for small datasets but becomes a serious performance problem as the underlying table grows.

उदाहरण: Server-Side Filtering, Sorting, and Pagination

javascript
const page = 2, sortBy = "name";
fetch(`get-users.php?page=${page}&sort=${sortBy}`)
  .then(r => r.json())
  .then(rows => console.log(rows)); // filtering/sorting done server-side

Handling Loading and Empty States

A database-backed AJAX request can take a noticeable moment, and might return zero matching rows -- a polished UI shows a loading indicator while waiting, and a clear "no results" message rather than a blank area when the response contains an empty array.

Note: Always design an explicit empty state (a friendly "no results found" message) for any list rendered from an AJAX response, rather than letting an empty array silently produce a blank section.
Warning: Leaving no visual feedback during a database-backed request that takes a second or more can make the interface feel broken or unresponsive, even though it is working correctly.

उदाहरण: Handling Loading and Empty States

javascript
// Assign "<p>Loading...</p>" to `document.body.innerHTML`
// Assign "<p>Loading...</p>" to `document.body.innerHTML`
document.body.innerHTML = "<p>Loading...</p>";
// Define the method `fetch` taking `"get-users.php"`
// Define the method `fetch` taking `"get-users.php"`
fetch("get-users.php")
  // On success, run this with the resolved value as `r`
  // On success, run this with the resolved value as `r`
  .then(r => r.json())
  // On success, run this with the resolved value as `rows`
  // On success, run this with the resolved value as `rows`
  .then(rows => {
    // Assign `rows.length ? JSON.stringify(rows) : "<p>No results</p>"` to `document.body.innerHTML`
    // Assign `rows.length ? JSON.stringify(rows) : "<p>No results</p>"` to `document.body.innerHTML`
    document.body.innerHTML = rows.length ? JSON.stringify(rows) : "<p>No results</p>";
  });

Error Handling for Database-Backed Endpoints

A database query can fail for reasons entirely outside the client's control -- a connection issue, a constraint violation -- and the server should catch these, log the real detail, and return a generic, safe error message that the JavaScript displays without exposing internal database details to the user.

Note: Design database-backed AJAX endpoints to always return a consistent error shape on failure, so the client-side error handling code stays simple and predictable.
Warning: Displaying a raw database error message directly to the end user (passed through unfiltered from the server) can both confuse users and leak sensitive backend details.

उदाहरण: Error Handling for Database-Backed Endpoints

javascript
fetch("get-users.php")
  .then(response => {
    if (!response.ok) throw new Error("Something went wrong");
    return response.json();
  })
  .then(rows => console.log(rows))
  .catch(() => console.log("Unable to load data right now")); // no internal DB details exposed
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.