Axios and HTTP Libraries
Learning Objectives
- By the end of this lesson, you will be able to:
- - Install and use Axios
- - Compare Axios with Fetch API
- - Use request and response interceptors
- - Handle errors with Axios
- - Configure Axios instances
- - Work with other HTTP libraries
- - Choose the right HTTP client for your project
Lesson 12.2: Axios and HTTP Libraries
Learning Objectives
By the end of this lesson, you will be able to:
- Install and use Axios
- Compare Axios with Fetch API
- Use request and response interceptors
- Handle errors with Axios
- Configure Axios instances
- Work with other HTTP libraries
- Choose the right HTTP client for your project
Introduction to Axios
Axios is a popular HTTP client library for JavaScript. It provides a simple API and additional features compared to the native Fetch API.
Why Axios?
- Promise-based: Works with async/await
- Automatic JSON: Automatically parses JSON
- Interceptors: Request/response interceptors
- Error Handling: Better error handling
- Request Cancellation: Cancel requests
- Browser & Node.js: Works in both environments
Installing Axios
npm Installation
npm install axios
CDN (Browser)
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
Import Axios
// ES6 Modules
import axios from 'axios';
// CommonJS
const axios = require('axios');
Basic Axios Usage
GET Request
// Simple GET
axios.get('https://api.example.com/users')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error:', error);
});
// With async/await
async function getUsers() {
try {
const response = await axios.get('https://api.example.com/users');
console.log(response.data);
return response.data;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
POST Request
// POST request
axios.post('https://api.example.com/users', {
name: 'Alice',
email: 'alice@example.com'
})
.then(response => {
console.log('Created:', response.data);
})
.catch(error => {
console.error('Error:', error);
});
// With async/await
async function createUser(userData) {
try {
const response = await axios.post('https://api.example.com/users', userData);
return response.data;
} catch (error) {
console.error('Error creating user:', error);
throw error;
}
}
PUT Request
async function updateUser(userId, userData) {
try {
const response = await axios.put(`https://api.example.com/users/${userId}`, userData);
return response.data;
} catch (error) {
console.error('Error updating user:', error);
throw error;
}
}
DELETE Request
async function deleteUser(userId) {
try {
const response = await axios.delete(`https://api.example.com/users/${userId}`);
return response.data;
} catch (error) {
console.error('Error deleting user:', error);
throw error;
}
}
Axios vs Fetch
Comparison Table
| Feature | Fetch | Axios |
|---|---|---|
| JSON Parsing | Manual (response.json()) | Automatic |
| Request Cancellation | AbortController | Built-in |
| Interceptors | No | Yes |
| Error Handling | Manual check | Automatic |
| Browser Support | Modern browsers | All browsers |
| Bundle Size | Built-in (0KB) | ~13KB |
| Request Timeout | Manual | Built-in |
| Response Timeout | No | Yes |
Code Comparison
Fetch:
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'Alice' })
})
.then(response => {
if (!response.ok) {
throw new Error('HTTP error');
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error(error));
Axios:
axios.post('https://api.example.com/users', { name: 'Alice' })
.then(response => console.log(response.data))
.catch(error => console.error(error));
Request Configuration
Config Object
axios({
method: 'POST',
url: 'https://api.example.com/users',
data: {
name: 'Alice',
email: 'alice@example.com'
},
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
timeout: 5000,
params: {
page: 1,
limit: 10
}
});
Common Config Options
axios.get('https://api.example.com/users', {
params: {
page: 1,
limit: 10
},
headers: {
'Authorization': 'Bearer token123'
},
timeout: 5000,
responseType: 'json' // json, text, blob, arraybuffer
});
Response Object
Response Structure
const response = await axios.get('https://api.example.com/users');
console.log(response.data); // Response body (parsed)
console.log(response.status); // HTTP status code
console.log(response.statusText); // HTTP status text
console.log(response.headers); // Response headers
console.log(response.config); // Request config
Accessing Data
// Axios automatically parses JSON
const response = await axios.get('https://api.example.com/users');
const users = response.data; // Already parsed JSON
// For other types
const response = await axios.get('https://api.example.com/image.png', {
responseType: 'blob'
});
const image = response.data; // Blob object
Error Handling
Basic Error Handling
try {
const response = await axios.get('https://api.example.com/users');
console.log(response.data);
} catch (error) {
if (error.response) {
// Server responded with error status
console.error('Status:', error.response.status);
console.error('Data:', error.response.data);
} else if (error.request) {
// Request made but no response
console.error('No response:', error.request);
} else {
// Error setting up request
console.error('Error:', error.message);
}
}
Error Object Structure
catch (error) {
console.log(error.message); // Error message
console.log(error.response); // Response object (if received)
console.log(error.response.status); // HTTP status
console.log(error.response.data); // Response data
console.log(error.request); // Request object
console.log(error.config); // Request config
}
Handling Specific Status Codes
try {
const response = await axios.get('https://api.example.com/users');
} catch (error) {
if (error.response) {
switch (error.response.status) {
case 404:
console.error('Resource not found');
break;
case 401:
console.error('Unauthorized');
break;
case 500:
console.error('Server error');
break;
default:
console.error('Error:', error.response.status);
}
}
}
Interceptors
Request Interceptor
// Add token to all requests
axios.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
Response Interceptor
// Handle responses globally
axios.interceptors.response.use(
response => {
// Modify response before returning
return response;
},
error => {
// Handle errors globally
if (error.response?.status === 401) {
// Redirect to login
window.location.href = '/login';
}
return Promise.reject(error);
}
);
Multiple Interceptors
// Request interceptor 1
const requestInterceptor1 = axios.interceptors.request.use(config => {
console.log('Request 1:', config.url);
return config;
});
// Request interceptor 2
const requestInterceptor2 = axios.interceptors.request.use(config => {
config.headers['X-Custom'] = 'value';
return config;
});
// Remove interceptor
axios.interceptors.request.eject(requestInterceptor1);
Axios Instances
Creating an Instance
const apiClient = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
});
// Use instance
apiClient.get('/users')
.then(response => console.log(response.data));
Instance with Defaults
const apiClient = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000
});
// Add default header
apiClient.defaults.headers.common['Authorization'] = 'Bearer token123';
// Add interceptor to instance
apiClient.interceptors.request.use(config => {
console.log('API Request:', config.url);
return config;
});
Request Cancellation
Cancel Token (Axios < 0.22)
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('https://api.example.com/users', {
cancelToken: source.token
})
.then(response => console.log(response.data))
.catch(error => {
if (axios.isCancel(error)) {
console.log('Request cancelled');
}
});
// Cancel request
source.cancel('Operation cancelled');
AbortController (Axios >= 0.22)
const controller = new AbortController();
axios.get('https://api.example.com/users', {
signal: controller.signal
})
.then(response => console.log(response.data))
.catch(error => {
if (axios.isCancel(error)) {
console.log('Request cancelled');
}
});
// Cancel request
controller.abort();
Practical Examples
Example 1: API Client Class
class ApiClient {
constructor(baseURL) {
this.client = axios.create({
baseURL,
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
this.setupInterceptors();
}
setupInterceptors() {
// Request interceptor
this.client.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
// Response interceptor
this.client.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
}
async get(url, config) {
return this.client.get(url, config);
}
async post(url, data, config) {
return this.client.post(url, data, config);
}
async put(url, data, config) {
return this.client.put(url, data, config);
}
async delete(url, config) {
return this.client.delete(url, config);
}
}
// Usage
const api = new ApiClient('https://api.example.com');
const users = await api.get('/users');
Example 2: Error Handling Utility
function handleAxiosError(error) {
if (error.response) {
// Server responded with error
const { status, data } = error.response;
switch (status) {
case 400:
return { message: 'Bad request', details: data };
case 401:
return { message: 'Unauthorized', details: data };
case 404:
return { message: 'Not found', details: data };
case 500:
return { message: 'Server error', details: data };
default:
return { message: `HTTP error ${status}`, details: data };
}
} else if (error.request) {
// Request made but no response
return { message: 'No response from server', details: null };
} else {
// Error setting up request
return { message: error.message, details: null };
}
}
// Usage
try {
await axios.get('https://api.example.com/users');
} catch (error) {
const errorInfo = handleAxiosError(error);
console.error(errorInfo);
}
Practice Exercise
Exercise: Axios Practice
Objective: Practice using Axios for HTTP requests.
Instructions:
- Install Axios (or use CDN)
- Create a file called
axios-practice.js - Practice:
- GET, POST, PUT, DELETE requests
- Error handling
- Interceptors
- Creating instances
- Request cancellation
Example Solution:
// Axios Practice
// Note: Requires axios to be installed or loaded via CDN
const axios = require('axios'); // or import axios from 'axios';
const API_URL = 'https://jsonplaceholder.typicode.com';
console.log("=== Basic GET Request ===");
async function getUsers() {
try {
const response = await axios.get(`${API_URL}/users`);
console.log(`Fetched ${response.data.length} users`);
return response.data;
} catch (error) {
console.error('Error:', error.message);
throw error;
}
}
getUsers();
console.log();
console.log("=== GET with Params ===");
async function getUserPosts(userId) {
try {
const response = await axios.get(`${API_URL}/posts`, {
params: {
userId: userId
}
});
console.log(`User ${userId} has ${response.data.length} posts`);
return response.data;
} catch (error) {
console.error('Error:', error.message);
throw error;
}
}
getUserPosts(1);
console.log();
console.log("=== POST Request ===");
async function createPost(postData) {
try {
const response = await axios.post(`${API_URL}/posts`, postData);
console.log('Created post:', response.data.id);
return response.data;
} catch (error) {
console.error('Error creating post:', error.message);
throw error;
}
}
createPost({
title: 'My New Post',
body: 'This is the body',
userId: 1
});
console.log();
console.log("=== PUT Request ===");
async function updatePost(postId, updates) {
try {
const response = await axios.put(`${API_URL}/posts/${postId}`, updates);
console.log('Updated post:', response.data.id);
return response.data;
} catch (error) {
console.error('Error updating post:', error.message);
throw error;
}
}
updatePost(1, {
title: 'Updated Title',
body: 'Updated body',
userId: 1
});
console.log();
console.log("=== DELETE Request ===");
async function deletePost(postId) {
try {
const response = await axios.delete(`${API_URL}/posts/${postId}`);
console.log(`Post ${postId} deleted`);
return response.data;
} catch (error) {
console.error('Error deleting post:', error.message);
throw error;
}
}
deletePost(1);
console.log();
console.log("=== Error Handling ===");
async function handleErrors() {
try {
await axios.get(`${API_URL}/invalid-endpoint`);
} catch (error) {
if (error.response) {
console.log('Status:', error.response.status);
console.log('Data:', error.response.data);
} else if (error.request) {
console.log('No response received');
} else {
console.log('Error:', error.message);
}
}
}
handleErrors();
console.log();
console.log("=== Request Interceptor ===");
// Add token to all requests
axios.interceptors.request.use(
config => {
const token = 'mock-token-123';
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
console.log('Request interceptor:', config.url);
return config;
},
error => {
return Promise.reject(error);
}
);
axios.get(`${API_URL}/users/1`)
.then(response => {
console.log('Request completed with interceptor');
});
console.log();
console.log("=== Response Interceptor ===");
axios.interceptors.response.use(
response => {
console.log('Response interceptor:', response.status);
return response;
},
error => {
if (error.response?.status === 404) {
console.log('404 error intercepted');
}
return Promise.reject(error);
}
);
axios.get(`${API_URL}/users/1`)
.then(response => {
console.log('Response received');
});
console.log();
console.log("=== Axios Instance ===");
const apiClient = axios.create({
baseURL: API_URL,
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
});
// Use instance
apiClient.get('/users/1')
.then(response => {
console.log('Instance request successful');
});
console.log();
console.log("=== Request Cancellation ===");
const controller = new AbortController();
setTimeout(() => {
controller.abort();
console.log('Request cancelled');
}, 100);
try {
await axios.get(`${API_URL}/users`, {
signal: controller.signal
});
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request was cancelled');
} else {
console.error('Error:', error.message);
}
}
Expected Output (will vary):
=== Basic GET Request ===
Fetched 10 users
=== GET with Params ===
User 1 has 10 posts
=== POST Request ===
Created post: 101
=== PUT Request ===
Updated post: 1
=== DELETE Request ===
Post 1 deleted
=== Error Handling ===
Status: 404
Data: {}
=== Request Interceptor ===
Request interceptor: https://jsonplaceholder.typicode.com/users/1
Request completed with interceptor
=== Response Interceptor ===
Response interceptor: 200
Response received
=== Axios Instance ===
Instance request successful
=== Request Cancellation ===
Request cancelled
Request was cancelled
Challenge (Optional):
- Build a complete API client with Axios
- Create reusable interceptors
- Implement retry logic
- Build error handling utilities
Common Mistakes
1. Not Handling Errors
// ⚠️ Problem: No error handling
const response = await axios.get(url);
console.log(response.data);
// ✅ Solution: Always handle errors
try {
const response = await axios.get(url);
console.log(response.data);
} catch (error) {
console.error('Error:', error);
}
2. Accessing Wrong Property
// ⚠️ Problem: Wrong property
const data = await axios.get(url);
console.log(data); // Response object, not data
// ✅ Solution: Use response.data
const response = await axios.get(url);
console.log(response.data); // Actual data
3. Not Using Interceptors Properly
// ⚠️ Problem: Interceptor not returning config
axios.interceptors.request.use(config => {
config.headers.Auth = 'token';
// Missing return!
});
// ✅ Solution: Always return config
axios.interceptors.request.use(config => {
config.headers.Auth = 'token';
return config;
});
Key Takeaways
- Axios: Popular HTTP client library
- Automatic JSON: Parses JSON automatically
- Interceptors: Request/response interceptors
- Error Handling: Better error handling than Fetch
- Instances: Create configured instances
- Cancellation: Cancel requests
- Best Practice: Use interceptors for common logic
- When to Use: When you need features beyond Fetch
Quiz: HTTP Libraries
Test your understanding with these questions:
-
Axios automatically:
- A) Parses JSON
- B) Handles errors
- C) Both A and B
- D) Neither
-
Interceptors are used for:
- A) Request modification
- B) Response modification
- C) Both A and B
- D) Error handling only
-
Axios instance is created with:
- A) axios.create()
- B) new Axios()
- C) axios.instance()
- D) axios.new()
-
Axios vs Fetch:
- A) Axios is built-in
- B) Fetch needs more code
- C) Both are same
- D) Fetch is better
-
Error.response contains:
- A) Status code
- B) Response data
- C) Both A and B
- D) Request data
-
Request cancellation uses:
- A) AbortController
- B) CancelToken
- C) Both (depending on version)
- D) Neither
-
Axios is:
- A) Only for browsers
- B) Only for Node.js
- C) Both browser and Node.js
- D) Neither
Answers:
- C) Both A and B
- C) Both A and B
- A) axios.create()
- B) Fetch needs more code (Axios is simpler)
- C) Both A and B
- C) Both (depending on version)
- C) Both browser and Node.js
Next Steps
Congratulations! You've learned Axios. You now know:
- How to use Axios for HTTP requests
- How Axios compares to Fetch
- How to use interceptors
- How to handle errors with Axios
What's Next?
- Lesson 12.3: Working with JSON
- Learn JSON manipulation
- Practice API data handling
- Build complete API integrations
Additional Resources
- Axios Documentation: axios-http.com
- Axios GitHub: github.com/axios/axios
- Axios vs Fetch: Comparison guides
Lesson completed! You're ready to move on to the next lesson.
Course Navigation
Advanced Functions
Asynchronous JavaScript
Iterators and Generators