Using Axios in Vanilla JS: A Beginner’s Guide
Axios is a promise-based library for making HTTP requests that enhances the ease of making API calls compared to the standard XMLHttpRequest or the newer fetch API. Although commonly linked with React or Node.js, it works equally well in pure JavaScript projects, offering automatic JSON conversion, request/response interceptors, and improved error management right out of the box. This tutorial will guide you through the process of integrating Axios in your vanilla JS applications, from basic GET requests to complex configurations and real-world troubleshooting techniques.
Understanding Axios in Pure JavaScript
Axios functions as a wrapper around XMLHttpRequest in the browser, providing a promise-based interface that streamlines HTTP actions. Unlike fetch(), Axios simplifies JSON parsing, automatically throws errors for HTTP status issues, and facilitates straightforward options for transforming requests and responses.
You can include Axios in your vanilla JavaScript projects by either using a CDN link or downloading the library for local use. Once integrated, Axios provides a global object with methods aligned with HTTP verbs (GET, POST, PUT, DELETE, etc.), alongside configuration settings for headers, timeouts, and interceptors.
Feature | Axios | Fetch API | XMLHttpRequest |
---|---|---|---|
JSON Handling | Automatic | Manual (.json()) | Manual (JSON.parse) |
Error Handling | Throws on 4xx/5xx | Only network errors | Manual status checking |
Request Timeout | Built-in | Requires AbortController | Built-in |
Interceptors | Yes | ||
Browser Support | IE11+ | Modern browsers | All browsers |
A Comprehensive Guide for Implementation
Starting with Axios in your vanilla JavaScript project requires minimal effort. Below is a straightforward method to incorporate it:
Installation and Initial Setup
To add Axios to your HTML document, use the following CDN:
Alternatively, download and serve it locally:
Executing a Basic GET Request
Begin with a simple GET request to retrieve data from an API:
// Basic GET request
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('Data:', response.data);
console.log('Status:', response.status);
console.log('Headers:', response.headers);
})
.catch(error => {
console.error('Error:', error.message);
});
Making a POST Request with Data
Here's how to send information to an API endpoint:
const postData = {
title: 'New Post',
body: 'This is the post content',
userId: 1
};
axios.post('https://jsonplaceholder.typicode.com/posts', postData)
.then(response => {
console.log('Created:', response.data);
document.getElementById('result').innerHTML =
<p>Post created with ID: ${response.data.id}</p>
;
})
.catch(error => {
console.error('Failed to create post:', error);
});
Advanced Configuration Options
Create a custom Axios instance for tailored configurations:
const apiClient = axios.create({
baseURL: 'https://api.example.com/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token-here'
}
});
// Use the configured instance
apiClient.get('/users')
.then(response => {
displayUsers(response.data);
})
.catch(handleApiError);
Practical Examples and Scenarios
Loading Dynamic Content
A frequent application is the dynamic loading of content without refreshing the page:
class ContentLoader {
constructor(baseUrl) {
this.api = axios.create({
baseURL: baseUrl,
timeout: 5000
});
}
async loadArticle(articleId) {
try {
const response = await this.api.get(/articles/${articleId}
);
this.renderArticle(response.data);
} catch (error) {
this.showError('Failed to load article');
}
}
renderArticle(article) {
document.getElementById('article-content').innerHTML = `
${article.content}
Published: ${article.publishedAt}
`;
}
showError(message) {
document.getElementById('error-message').style.display = 'block';
document.getElementById('error-message').textContent = message;
}
}
Form Submission with Validation
Manage form submissions while ensuring proper error handling and user feedback:
document.getElementById('contact-form').addEventListener('submit', async (e) => { e.preventDefault();
const formData = new FormData(e.target); const data = Object.fromEntries(formData.entries());
// Show loading state const submitBtn = document.getElementById('submit-btn'); submitBtn.disabled = true; submitBtn.textContent="Sending...";
try { const response = await axios.post('/api/contact', data, { headers: { 'Content-Type': 'application/json' } });
showSuccessMessage('Message sent successfully!'); e.target.reset();
} catch (error) {
if (error.response && error.response.status === 422) {
showValidationErrors(error.response.data.errors);
} else {
showErrorMessage('Failed to send message. Please try again.');
}
} finally {
submitBtn.disabled = false;
submitBtn.textContent="Send Message";
}
});Utilising Interceptors for Global Management
Interceptors facilitate the global handling of requests and responses:
// Request interceptor - attach auth token to all requests axios.interceptors.request.use( config => { const token = localStorage.getItem('authToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, error => Promise.reject(error) );
// Response interceptor - manage common errors axios.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { // Redirect to login page window.location.href = "https://Digitalberg.net/login"; } else if (error.response?.status === 500) { showGlobalError('server error. Please try again later.'); } return Promise.reject(error); } );
Recommended Practices and Common Mistakes
Recommended Practices
- Use async/await for cleaner, more readable code instead of chaining .then() calls
- Set appropriate timeouts to prevent requests from hanging indefinitely
- Implement rigorous error management for different HTTP status codes
- Leverage interceptors for handling cross-cutting concerns like authentication
- Create instances with custom settings rather than relying on the global axios object
- Validate data before submission to minimize server errors
Common Mistakes and Fixes
CORS Issues: When making requests to different origins, ensure that the server is sending the correct CORS headers. Note that you cannot resolve CORS issues from the client side:
// Adjusting headers won't resolve CORS issues
axios.get('https://external-api.com/data', {
headers: {
'Access-Control-Allow-Origin': '*' // Incorrect approach
}
});
Memory Leaks and Interceptors: Always remove interceptors when they are no longer necessary:
// Store the interceptor ID
const requestInterceptor = axios.interceptors.request.use(config => config);
// Remove it later
axios.interceptors.request.eject(requestInterceptor);
Network Error Handling: Differentiate between network errors and HTTP errors:
axios.get('/api/data')
.catch(error => {
if (error.response) {
// server responded with error status
console.log('server Error:', error.response.status);
} else if (error.request) {
// Request made but no response received
console.log('Network Error:', error.request);
} else {
// Other errors
console.log('Error:', error.message);
}
});
Performance Considerations
Incorporating Axios adds around 40KB to your bundle size when minified, which is a reasonable trade-off for its functionality. Here are some tips to optimise performance:
- Request Cancellation: Use AbortController to cancel requests as components unmount or when new requests replace old ones
- Caching Responses: Implement caching strategies for frequently accessed data to alleviate server strain
- Connection Pooling: While Axios reuses connections automatically, be aware of limits on concurrent requests
// Example of request cancellation
const source = axios.CancelToken.source();
axios.get('/api/search', {
cancelToken: source.token,
params: { q: searchQuery }
}).catch(thrown => {
if (axios.isCancel(thrown)) {
console.log('Request cancelled');
}
});
// Cancel the request if necessary
if (newSearchQuery !== searchQuery) {
source.cancel('Operation cancelled by user');
}
Troubleshooting Frequent Problems
Request Timeouts: If you experience timeouts with slow APIs, consider raising the timeout values or implementing a retry mechanism:
const axiosRetry = async (url, options = {}, retries = 3) => {
try {
return await axios.get(url, { timeout: 5000, ...options });
} catch (error) {
if (retries > 0 && error.code === 'ECONNABORTED') {
console.log(`Retrying... ${retries} attempts remaining`);
return axiosRetry(url, options, retries - 1);
}
throw error;
}
};
Content-Type Misconfigurations: Ensure the correct Content-Type header is set:
// For submitting form data
const formData = new FormData();
formData.append('file', fileInput.files[0]);
axios.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
// For URL-encoded data
const params = new URLSearchParams();
params.append('key', 'value');
axios.post('/api/form', params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
For in-depth documentation and advanced usage patterns, please refer to the official Axios documentation. The GitHub repository also provides extensive examples and troubleshooting resources for more intricate cases.
The content of this article includes insights and information from various online sources. We recognise and value the contributions of all original authors, publishers, and websites. Every effort has been taken to appropriately credit these sources, and any unintentional oversights do not constitute copyright infringement. All trademarks, logos, and images are the property of their respective owners. If you believe any content used herein infringes your copyright, please contact us promptly for assessment and resolution.
This article is intended for informational and educational purposes, and does not violate copyright laws. If any copyrighted material has been utilized improperly or without proper acknowledgment, it is unintentional, and we will make necessary adjustments immediately upon notification. Please note that republishing, redistributing, or reproducing any part or all of this content in any form is prohibited without explicit written consent from the author and website owner. For permissions or further inquiries, please reach out to us.