Connecting to web services and third-party REST APIs is an essential building block of modern web development. Whether you are consuming public datasets, sending form inputs, or building interactive web applications, JavaScript provides built-in tools like the Promise-based Fetch API and async/await syntax to manage network requests cleanly.
Prerequisites
- Basic understanding of modern JavaScript (ES6+).
- Familiarity with asynchronous concepts: Promises and
async/await. - A browser developer console or local Node.js environment for testing.
Method 1: The Modern Standard — Fetch API with Async/Await
The native fetch() method is the industry standard for modern web browsers. Using async/await alongside try...catch provides a readable, synchronous-looking style for asynchronous network calls.
async function fetchUserData(userId) {
const url = `https://jsonplaceholder.typicode.com/users/${userId}`;
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
// Check if the response status is in the 200-299 range
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status} - ${response.statusText}`);
}
const data = await response.json();
console.log('User Record:', data);
return data;
} catch (error) {
console.error('Network or Parsing Error:', error.message);
throw error;
}
}
// Execute the call
fetchUserData(1);
fetch() does not reject a Promise on HTTP 404 (Not Found) or HTTP 500 (Internal Server Error) status codes. It only rejects on severe network failures or blocked requests. You must manually verify response.ok before calling response.json().
Sending Data: Making a POST Request
To send payloads to a backend endpoint, define the HTTP method, serialize your body data with JSON.stringify(), and set the Content-Type header:
async function createPost(payload) {
const url = 'https://jsonplaceholder.typicode.com/posts';
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Failed to create post. Status: ${response.status}`);
}
const result = await response.json();
console.log('Created Record:', result);
return result;
} catch (error) {
console.error('Submission failed:', error.message);
}
}
// Sample invocation
createPost({
title: 'Modern Web Architecture',
body: 'Exploring asynchronous JavaScript patterns.',
userId: 101
});
Method 2: Legacy XMLHttpRequest (XHR)
Before the Fetch API arrived, XMLHttpRequest was the primary way to perform AJAX calls. While still supported across all browsers, its callback-heavy architecture is largely replaced by modern Fetch in new codebases.
function makeXhrRequest(url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
const responseData = JSON.parse(xhr.responseText);
console.log('XHR Response:', responseData);
} else {
console.error('Server returned an error:', xhr.statusText);
}
};
xhr.onerror = function () {
console.error('Network request failed completely.');
};
xhr.send();
}
Method 3: Third-Party Libraries (Axios)
Third-party HTTP client libraries like Axios remain popular for large applications because they provide automatic JSON parsing, request/response interceptors, and default error rejection on 4xx/5xx status codes.
// Example using Axios (requires: npm install axios or CDN script)
import axios from 'axios';
async function getAccountInfo() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users/1');
// Axios automatically parses JSON into response.data
console.log(response.data);
} catch (error) {
// Axios automatically catches non-2xx status codes
console.error('Axios Error:', error.response?.status, error.message);
}
}
- Native Fetch API: Zero bundle overhead, built directly into modern browsers, standard for lightweight applications.
- Axios Library: Best for enterprise frontends needing global interceptors, automatic CSRF token management, and request timeouts.
- CORS Considerations: Cross-Origin Resource Sharing (CORS) errors occur when the destination server does not allow calls from your browser's origin. Resolve this on the server by enabling CORS headers or routing requests through a backend proxy.
- Aborting Requests: Use the native
AbortControllerAPI withfetch()to cancel pending network requests when a user navigates away.
async/await and explicit response.ok validation to build fast, lightweight, and dependable network integrations.