Explain fetch API.
The Fetch API provides a modern, powerful, and flexible way to make network requests in the browser, serving as a promise-based replacement for XMLHttpRequest (XHR). It offers a more robust and streamlined interface for fetching resources across the network.
What is the Fetch API?
At its core, the Fetch API allows you to make HTTP requests to retrieve resources. It returns a Promise that resolves to a Response object, making asynchronous operations much easier to manage compared to older methods. It supports all standard HTTP methods (GET, POST, PUT, DELETE, etc.), custom headers, and various body types.
Basic Usage (GET Request)
The simplest use case for fetch() is to make a GET request to a URL. The fetch() function takes a mandatory resource argument, which is the URL to fetch. It returns a Promise that, when fulfilled, yields a Response object.
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json(); // or .text(), .blob(), etc.
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
In this example, response.json() is another Promise that parses the response body as JSON. We chain .then() calls to handle the successful response data and a .catch() block to handle any network errors or errors thrown during the promise chain.
Handling Responses and Errors
It's crucial to understand that fetch() only rejects a Promise if a network error occurs (e.g., no internet connection). It does not reject for HTTP errors like 404 Not Found or 500 Internal Server Error. For these, you must manually check the response.ok property (a boolean indicating if the HTTP status code is in the 200-299 range) or response.status (the actual status code).
async function fetchData() {
try {
const response = await fetch('https://api.example.com/nonexistent');
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'No JSON error details' }));
throw new Error(`HTTP error! Status: ${response.status}, Message: ${errorData.message || 'Unknown error'}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Fetch operation failed:', error.message);
}
}
Making POST Requests
To make requests other than GET, you pass an options object as the second argument to fetch(). This object can specify the method, headers, and body of the request.
const postData = {
title: 'foo',
body: 'bar',
userId: 1
};
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Post created:', data);
})
.catch(error => {
console.error('Error creating post:', error);
});
Here, Content-Type: application/json is crucial for the server to correctly parse the JSON string in the body. JSON.stringify() converts the JavaScript object into a JSON string.
Key Features and Benefits
- Promise-based: Simplifies asynchronous code with
.then()and.catch()syntax, and integrates well withasync/await. - Modern and Flexible: Part of the Web API standard, designed for modern web development.
- Separation of Concerns: Clearly separates the
RequestandResponseobjects from the networking process. - Stream Support: Can handle streams for both requests and responses, allowing for efficient handling of large files.
- Security: Supports various security features, including CORS.
Conclusion
The Fetch API is the de facto standard for making network requests in modern web browsers. Its promise-based nature, flexibility, and powerful features make it a superior choice over older methods like XMLHttpRequest. Mastering fetch() is essential for any JavaScript developer working with client-server communication.