Fetch API + Axios
Learn to make HTTP requests using both the native Fetch API and the popular Axios library.
Fetch API Basics
javascript// Basic GET request fetch('https://jsonplaceholder.typicode.com/posts/1') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); // With async/await async function fetchPost(id) { try { const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('Fetch error:', error); throw error; } } // POST request async function createPost(postData) { const response = await fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(postData) }); return response.json(); } // Usage const newPost = await createPost({ title: 'My New Post', body: 'This is the content', userId: 1 });
Fetch API Advanced Features
javascript// Request with custom headers and options async function fetchWithOptions(url, options = {}) { const defaultOptions = { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('token') }, credentials: 'include', // Include cookies cache: 'no-cache' }; const config = { ...defaultOptions, ...options }; const response = await fetch(url, config); // Handle different response types const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return response.json(); } else if (contentType && contentType.includes('text/')) { return response.text(); } else { return response.blob(); } } // File upload async function uploadFile(file) { const formData = new FormData(); formData.append('file', file); formData.append('description', 'Uploaded file'); const response = await fetch('/api/upload', { method: 'POST', body: formData // Don't set Content-Type header for FormData }); return response.json(); } // Request timeout function fetchWithTimeout(url, options = {}, timeout = 5000) { return Promise.race([ fetch(url, options), new Promise((_, reject) => setTimeout(() => reject(new Error('Request timeout')), timeout) ) ]); } // Retry mechanism async function fetchWithRetry(url, options = {}, maxRetries = 3) { let lastError; for (let i = 0; i <= maxRetries; i++) { try { const response = await fetch(url, options); if (response.ok) { return response; } throw new Error(`HTTP ${response.status}: ${response.statusText}`); } catch (error) { lastError = error; if (i < maxRetries) { await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); } } } throw lastError; }
Axios Basics
javascript// Install: npm install axios // import axios from 'axios'; // Basic GET request axios.get('https://jsonplaceholder.typicode.com/posts/1') .then(response => console.log(response.data)) .catch(error => console.error('Error:', error)); // With async/await async function fetchPostAxios(id) { try { const response = await axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`); return response.data; } catch (error) { console.error('Axios error:', error.response?.data || error.message); throw error; } } // POST request async function createPostAxios(postData) { const response = await axios.post('https://jsonplaceholder.typicode.com/posts', postData); return response.data; } // Multiple HTTP methods const api = { get: (url) => axios.get(url), post: (url, data) => axios.post(url, data), put: (url, data) => axios.put(url, data), patch: (url, data) => axios.patch(url, data), delete: (url) => axios.delete(url) };
Axios Configuration and Interceptors
javascript// Create axios instance with default config const apiClient = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('token') } }); // Request interceptor apiClient.interceptors.request.use( (config) => { // Add timestamp to all requests config.params = { ...config.params, timestamp: Date.now() }; console.log('Request sent:', config); return config; }, (error) => { console.error('Request error:', error); return Promise.reject(error); } ); // Response interceptor apiClient.interceptors.response.use( (response) => { console.log('Response received:', response); return response; }, (error) => { if (error.response?.status === 401) { // Handle unauthorized access localStorage.removeItem('token'); window.location.href = '/login'; } return Promise.reject(error); } ); // Global error handling axios.defaults.validateStatus = function (status) { return status >= 200 && status < 300; // Default }; // Custom error handling apiClient.interceptors.response.use( response => response, error => { const customError = { message: error.message, status: error.response?.status, data: error.response?.data, url: error.config?.url }; return Promise.reject(customError); } );
Practical API Client
javascriptclass ApiService { constructor(baseURL) { this.client = axios.create({ baseURL, timeout: 10000, headers: { 'Content-Type': 'application/json' } }); this.setupInterceptors(); } setupInterceptors() { // Request interceptor for auth this.client.interceptors.request.use( (config) => { const token = localStorage.getItem('authToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); // Response interceptor for error handling this.client.interceptors.response.use( (response) => response.data, (error) => { if (error.response?.status === 401) { this.handleUnauthorized(); } return Promise.reject(this.formatError(error)); } ); } handleUnauthorized() { localStorage.removeItem('authToken'); // Redirect to login or emit event window.dispatchEvent(new CustomEvent('unauthorized')); } formatError(error) { return { message: error.response?.data?.message || error.message, status: error.response?.status, code: error.response?.data?.code }; } // HTTP methods async get(url, params = {}) { return this.client.get(url, { params }); } async post(url, data) { return this.client.post(url, data); } async put(url, data) { return this.client.put(url, data); } async patch(url, data) { return this.client.patch(url, data); } async delete(url) { return this.client.delete(url); } // File upload async uploadFile(url, file, onProgress) { const formData = new FormData(); formData.append('file', file); return this.client.post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' }, onUploadProgress: onProgress }); } // Download file async downloadFile(url, filename) { const response = await this.client.get(url, { responseType: 'blob' }); const blob = new Blob([response.data]); const downloadUrl = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = filename; link.click(); window.URL.revokeObjectURL(downloadUrl); } } // Usage const api = new ApiService('https://api.example.com'); // CRUD operations const users = await api.get('/users'); const user = await api.get('/users/1'); const newUser = await api.post('/users', { name: 'John', email: 'john@example.com' }); const updatedUser = await api.put('/users/1', { name: 'Jane' }); await api.delete('/users/1');
Comparison: Fetch vs Axios
javascript// Fetch API async function fetchExample() { try { const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token' }, body: JSON.stringify({ name: 'John' }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { console.error('Fetch error:', error); throw error; } } // Axios equivalent async function axiosExample() { try { const response = await axios.post('/api/users', { name: 'John' }, { headers: { 'Authorization': 'Bearer token' } } ); return response.data; } catch (error) { console.error('Axios error:', error.response?.data || error.message); throw error; } } // Concurrent requests // Fetch async function fetchConcurrent() { const [users, posts] = await Promise.all([ fetch('/api/users').then(r => r.json()), fetch('/api/posts').then(r => r.json()) ]); return { users, posts }; } // Axios async function axioConcurrent() { const [users, posts] = await Promise.all([ axios.get('/api/users'), axios.get('/api/posts') ]); return { users: users.data, posts: posts.data }; } // Request cancellation // Fetch with AbortController function fetchWithCancel() { const controller = new AbortController(); const request = fetch('/api/data', { signal: controller.signal }); // Cancel after 5 seconds setTimeout(() => controller.abort(), 5000); return request; } // Axios with cancel token function axiosWithCancel() { const source = axios.CancelToken.source(); const request = axios.get('/api/data', { cancelToken: source.token }); // Cancel after 5 seconds setTimeout(() => source.cancel('Request timeout'), 5000); return request; }