Sitemap

Fetch API in java-scripts

5 min readFeb 9, 2025

--

I have create a comprehensive guide for the Fetch API in JavaScript with following examples covering different use cases and cover error handling.

```javascript
// Basic GET Request
fetch(‘https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(‘Error:’, error));

// Complete Fetch API Wrapper with Error Handling
class APIClient {
constructor(baseURL) {
this.baseURL = baseURL;
}

// Common headers for all requests
#getHeaders() {
return {
‘Content-Type’: ‘application/json’,
‘Authorization’: `Bearer ${localStorage.getItem(‘token’)}`,
// Add custom headers as needed
};
}

// Handle response and errors
async #handleResponse(response) {
if (!response.ok) {
// Handle different error status codes
switch (response.status) {
case 400:
throw new Error(‘Bad Request — Invalid data’);
case 401:
throw new Error(‘Unauthorized — Please login’);
case 403:
throw new Error(‘Forbidden — Insufficient permissions’);
case 404:
throw new Error(‘Not Found — Resource doesn\’t exist’);
case 429:
throw new Error(‘Too Many Requests — Please try again later’);
case 500:
throw new Error(‘Server Error — Please try again later’);
default:
throw new Error(`HTTP error! status: ${response.status}`);
}
}

// Check content type and handle accordingly
const contentType = response.headers.get(‘content-type’);
if (contentType?.includes(‘application/json’)) {
return response.json();
} else if (contentType?.includes(‘text/plain’)) {
return response.text();
} else if (contentType?.includes(‘application/pdf’)) {
return response.blob();
}
return response;
}

// GET request
async get(endpoint, params = {}) {
try {
// Build URL with query parameters
const url = new URL(`${this.baseURL}${endpoint}`);
Object.keys(params).forEach(key =>
url.searchParams.append(key, params[key])
);

const response = await fetch(url, {
method: ‘GET’,
headers: this.#getHeaders(),
credentials: ‘include’, // For cookies
});

return await this.#handleResponse(response);
} catch (error) {
this.#handleError(error);
}
}

// POST request
async post(endpoint, data = {}) {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: ‘POST’,
headers: this.#getHeaders(),
credentials: ‘include’,
body: JSON.stringify(data),
});

return await this.#handleResponse(response);
} catch (error) {
this.#handleError(error);
}
}

// PUT request
async put(endpoint, data = {}) {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: ‘PUT’,
headers: this.#getHeaders(),
credentials: ‘include’,
body: JSON.stringify(data),
});

return await this.#handleResponse(response);
} catch (error) {
this.#handleError(error);
}
}

// DELETE request
async delete(endpoint) {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: ‘DELETE’,
headers: this.#getHeaders(),
credentials: ‘include’,
});

return await this.#handleResponse(response);
} catch (error) {
this.#handleError(error);
}
}

// Upload file
async uploadFile(endpoint, file, onProgress) {
try {
const formData = new FormData();
formData.append(‘file’, file);

const xhr = new XMLHttpRequest();

// Handle upload progress
if (onProgress) {
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
const progress = (event.loaded / event.total) * 100;
onProgress(progress);
}
};
}

// Return promise for XMLHttpRequest
return new Promise((resolve, reject) => {
xhr.open(‘POST’, `${this.baseURL}${endpoint}`);

// Add authorization header if needed
const token = localStorage.getItem(‘token’);
if (token) {
xhr.setRequestHeader(‘Authorization’, `Bearer ${token}`);
}

xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject(new Error(`Upload failed: ${xhr.status}`));
}
};

xhr.onerror = () => reject(new Error(‘Upload failed’));
xhr.send(formData);
});
} catch (error) {
this.#handleError(error);
}
}

// Download file
async downloadFile(endpoint) {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: ‘GET’,
headers: this.#getHeaders(),
});

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

Get kkrajpurohit’s stories in your inbox

Join Medium for free to get updates from this writer.

const blob = await response.blob();
const filename = response.headers.get(‘content-disposition’)
?.split(‘filename=’)[1]
?.replace(/[‘“]/g, ‘’) || ‘download’;

// Create download link
const url = window.URL.createObjectURL(blob);
const link = document.createElement(‘a’);
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
} catch (error) {
this.#handleError(error);
}
}

// Handle timeout
async fetchWithTimeout(endpoint, options = {}, timeout = 5000) {
try {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);

const response = await fetch(`${this.baseURL}${endpoint}`, {
…options,
signal: controller.signal,
});

clearTimeout(id);
return await this.#handleResponse(response);
} catch (error) {
if (error.name === ‘AbortError’) {
throw new Error(‘Request timed out’);
}
this.#handleError(error);
}
}

// Handle errors
#handleError(error) {
// Log error for debugging
console.error(‘API Error:’, error);

// Handle network errors
if (!navigator.onLine) {
throw new Error(‘No internet connection’);
}

// Handle timeout errors
if (error.name === ‘AbortError’) {
throw new Error(‘Request timed out’);
}

// Rethrow the error for the caller to handle
throw error;
}
}

// Usage Examples:
const api = new APIClient(‘https://api.example.com');

// Example 1: Basic GET request with query parameters
async function getUsers(page = 1, limit = 10) {
try {
const users = await api.get(‘/users’, { page, limit });
console.log(‘Users:’, users);
} catch (error) {
console.error(‘Failed to fetch users:’, error);
}
}

// Example 2: POST request with data
async function createUser(userData) {
try {
const newUser = await api.post(‘/users’, userData);
console.log(‘Created user:’, newUser);
} catch (error) {
console.error(‘Failed to create user:’, error);
}
}

// Example 3: File upload with progress
async function uploadUserAvatar(file) {
try {
await api.uploadFile(‘/users/avatar’, file, (progress) => {
console.log(`Upload progress: ${progress}%`);
});
console.log(‘Avatar uploaded successfully’);
} catch (error) {
console.error(‘Failed to upload avatar:’, error);
}
}

// Example 4: Download file
async function downloadReport() {
try {
await api.downloadFile(‘/reports/monthly’);
console.log(‘Report downloaded successfully’);
} catch (error) {
console.error(‘Failed to download report:’, error);
}
}

// Example 5: Request with timeout
async function getUsersWithTimeout() {
try {
const users = await api.fetchWithTimeout(‘/users’, { method: ‘GET’ }, 3000);
console.log(‘Users:’, users);
} catch (error) {
console.error(‘Request failed:’, error);
}
}

// Example 6: Handling multiple requests
async function getUserData(userId) {
try {
const [user, posts, comments] = await Promise.all([
api.get(`/users/${userId}`),
api.get(`/users/${userId}/posts`),
api.get(`/users/${userId}/comments`)
]);

return { user, posts, comments };
} catch (error) {
console.error(‘Failed to fetch user data:’, error);
}
}

// Example 7: Retry mechanism
async function fetchWithRetry(endpoint, options = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await api.get(endpoint, options);
} catch (error) {
if (i === maxRetries — 1) throw error;
// Wait before retrying (exponential backoff)
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, i) * 1000)
);
}
}
}

```

I’ve created a comprehensive Fetch API wrapper that handles various scenarios.
Here are the key features:

1. Basic Operations:
— GET, POST, PUT, DELETE requests
— Query parameter handling
— Custom headers
— Authentication token management

2. Error Handling:
— HTTP status code handling
— Network error detection
— Timeout handling
— Retry mechanism with exponential backoff

3. Data Types:
— JSON data
— Form data
— File uploads
— File downloads
— Text content
— Binary data (blobs)

4. Advanced Features:
— Progress tracking for uploads
— Request timeout
— Content type detection
— Cookie handling
— Multiple parallel requests
— File download with proper naming

5. Security:
— Authentication headers
— CORS handling
— Secure cookie handling

In future we will cover other example and Axios API.

--

--

kkrajpurohit
kkrajpurohit

Written by kkrajpurohit

0 followers

Hi, I'm K.K Rajpurohit, I love building utilities aimed at increasing Developer productivity .