4 min read14 hours ago
–
Intro
Hi there! Another weekend, another blog, and if you’re new here, I am @iamaangx028 👋
Quick continuity note: In Week 10, AJAX and modern client-server calls set the stage, and Week 11 dug into React state and control patterns — this one focuses on API calls and async flows that make the web feel instant. While it’s not mandatory to read last week’s blogs, it’s good to revise those concepts for better understanding.
Press enter or click to view image in full size
Let’s start Week — 12
Fetch — The modern AJAX way
Fetch is the browser-provided interface for requesting resources over the network, returning a Promise that resolves to a Response object, which can then be parsed as JSON, text, etc..
The basic syntax is fetch(url, [options]...
4 min read14 hours ago
–
Intro
Hi there! Another weekend, another blog, and if you’re new here, I am @iamaangx028 👋
Quick continuity note: In Week 10, AJAX and modern client-server calls set the stage, and Week 11 dug into React state and control patterns — this one focuses on API calls and async flows that make the web feel instant. While it’s not mandatory to read last week’s blogs, it’s good to revise those concepts for better understanding.
Press enter or click to view image in full size
Let’s start Week — 12
Fetch — The modern AJAX way
Fetch is the browser-provided interface for requesting resources over the network, returning a Promise that resolves to a Response object, which can then be parsed as JSON, text, etc..
The basic syntax is fetch(url, [options]), where options can include method, headers, and body, supporting common HTTP verbs like GET, POST, PUT, PATCH, and DELETE as needed.
// POST example with JSON bodyfetch("https://api.example.com/data", { method: "POST", // or GET, PUT, DELETE headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username: "aang", password: "1234" }),}) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error("Error:", error));
Under the hood, fetch is fully Promise-based, which is why it composes cleanly with then()/catch() and async/await patterns introduced below.
Modern apps often reach for fetch or Axios instead of raw XHR to keep code simpler while still getting async behavior without page reloads, as teased back in Week 10’s AJAX section.
Axios — A Friendly Wrapper Over HTTP
Axios is a small HTTP client library that many prefer for its straightforward API, sensible defaults, and ergonomic response handling (response.data just works). The async/await pattern makes Axios calls read like synchronous code, while still non-blocking the main thread.
import axios from "axios";async function sendData() { try { const response = await axios.post("https://api.example.com/data", { username: "aang", password: "1234", }); console.log(response.data); } catch (error) { console.error(error); }}
Axios supports the same verbs (GET, POST, PUT, DELETE, PATCH), works well with JSON by default, and integrates cleanly with Promise utilities like Promise. All for batching. Whether fetch or Axios is used, the key is an async mental model that treats network calls as “in-flight” work resolved by Promises.
Promises, async/await — The “I’ll get back to it” Model
A Promise represents a value that isn’t available yet but will be fulfilled or rejected in the future, letting the rest of the code keep moving without blocking. async marks a function as promise-returning, and await pauses inside that async function until the awaited Promise settles, at which point the fulfilled value is returned or the error is thrown.
- Write code, make a request to an external server, and continue running other logic while the response is pending — this is the Promise’s core value proposition in JavaScript.
- When the server responds, the Promise changes state to fulfilled (resolved) or rejected, and handlers or try/catch can act on that result immediately.
- async lets a function run asynchronously, so other parts don’t wait; await inside that async function pauses execution at that point until the Promise settles, producing a linear, readable flow for async code. A tiny but important rule: await can only be used inside an async function, while declaring an async function without await is allowed and simply returns a Promise. This pattern is why async/await often replaces long then chains with try/catch blocks that look synchronous but behave asynchronously.
Error handling — then/catch vs try/catch
With fetch or Axios, .then() runs on fulfillment and .catch() runs on rejection, making success and error paths explicit in a chained style. The same logic can be expressed with try/catch when using async/await, which many find easier to read for multi-step flows like
fetch → check status → parse → use
// then/catchfetch("https://api.example.com/data") .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error));// async/awaitasync function getData() { try { const response = await fetch("https://api.example.com/data"); const data = await response.json(); // converts to JSON console.log(data); } catch (error) { console.error(error); }}
As a practical habit, always ensure the network call is awaited before parsing or using the payload, and prefer surfacing network or parsing failures through a single error boundary with useful context. This keeps async flows deterministic while preserving readability in API orchestration code where multiple calls may need to be coordinated or retried.
- It’s fine to mark an async function without using await inside it; it still returns a Promise that can be handled upstream with then/catch if needed.
- await must be used inside an async function; using await in top-level code or a non-async function will throw a syntax error or require top-level await support in specific environments.
If you are a bug hunter, look for the followingbugs in JavaScript files
- Hardcoded sensitive tokens, config files, target company’s internal hosts, IP addresses, storage buckets, hidden endpoints, and hidden parameters. Organization’s employees’ emails, phone numbers, and even card details.
- Input handling and workflows: where validation happens, whether logic relies on client-side checks only, and how async/await or Promise chains gate critical steps.
- Dangerous DOM sinks: innerHTML, document.write, eval(), setTimeout(Function), new Function(), and flows linking tainted sources to these sinks (DOM XSS patterns).
- HTTP verbs and hidden surfaces: PUT/PATCH requests, feature flags, JS map files, and any references to admin or debug-only interfaces.
- Recon helpers: The Intigriti checklist and similar resources highlight how endpoints, parameters, and credentials often surface in shipped JS — treat JS as a discovery map.
- A resource that could be helpful for you! For deeper practice, Intigriti’s article on testing JavaScript files for bug bounty offers a compact checklist and common patterns worth bookmarking for ongoing recon.
Some Final Chit-Chats
I have spent most of the time making the blog & portfolio ready. So this week, I have covered only about fetch() and Axios for API calls, the Promise model behind async/await, and the exact places JavaScript code reveals interesting attack surface when reviewing a target’s frontend.
Got feedback or want to connect? Hit me up onX!