Requests
Modern applications are heavily reliant on data retrieved from the Internet. Whether it's pulling user information from a database, getting the latest posts from an API, or sending form data to a server - at some point, you will need to start sending HTTP requests.
The fetch API provides a simple and Promise-based way to make HTTP requests. It works in virtually all modern browsers, and
is natively supported by Node.js since version 18.
async function getHomepage() {
const request = await fetch('https://ts.coach')
const html = await request.text()
console.log(html)
}
getHomepage()
Links to child pages:
- If you are using an older version of node, install
node-fetch
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => {
console.log('Status:', response.status)
console.log('Content-Type:', response.headers.get('Content-Type'))
return response.json()
})
.then(console.log)
The simplest way to fetch data.
// Get text data
fetch('https://ts.coach')
.then(res => res.text())
.then(text => console.log('Text:', text))
// Get binary data (e.g., an image)
fetch('https://ts.coach/logo.png')
.then(res => res.blob())
.then(blob => console.log('Blob size:', blob.size))
// Get array buffer
fetch('https://ts.coach/logo.png')
.then(res => res.arrayBuffer())
.then(buffer => console.log('ArrayBuffer length:', buffer.byteLength))
The JSON Placeholder API provides a fast and reliable source for retrieving test data.
async function getTodo(id: number) {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/' + id)
const data = await response.json()
return data
}
getTodo(1).then(console.log)
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Hello World',
body: 'This is a post.',
userId: 1
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
const token = 'abc123';
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John Doe' })
})
.then(res => res.json())
.then(data => console.log('Saved:', data))
.catch(err => console.error('Error:', err));
The fetch API only rejects on network failures.
If the server responds with a 404 or 500 error, fetch still resolves the Promise and won't throw an error.
To check if the request succeeded, check response.ok.
fetch('https://jsonplaceholder.typicode.com/invalid-url')
.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('Fetch Error:', error));
Setting headers
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'GET',
headers: {
'Authorization': 'Bearer your-token-here',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Use the body as a stream instead of converting it all at once.
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => {
const reader = response.body!.getReader();
return reader.read();
})
.then(({ done, value }) => {
console.log(new TextDecoder().decode(value)); // Decode binary to text
});
TODO: create this as a browser based example
const formData = new FormData();
// formData.append('file', fileInput.files[0]);
fetch('/upload', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
To cancel a request with an AbortController.
const controller = new AbortController();
const signal = controller.signal;
fetch('https://jsonplaceholder.typicode.com/posts', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Request aborted');
} else {
console.error('Fetch error:', error);
}
});
// Abort the request after 2 seconds
setTimeout(() => controller.abort(), 2000);
Manages multiple requests in parallel.
const urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3',
];
async function fetchAll() {
const fetches = urls.map((url) => fetch(url).then((res) => res.json()))
const results = await Promise.all(fetches)
console.log(results)
}
fetchAll();
async function fetchWithRetry(url: string, retries: number = 3, delay: number = 1000) {
try {
const response = await fetch(url)
if (! response.ok)
throw new Error('Fetch failed')
return await res.json()
} catch (err) {
if (retries > 0) {
console.log(`Retrying... (${retries} left)`);
await new Promise((resolve) => setTimeout(resolve, delay))
return fetchWithRetry(url, retries - 1, delay)
}
else {
throw new Error('Fetch failed after retries');
}
}
}
fetchWithRetry('https://jsonplaceholder.typicode.com/posts/1').then(console.log);
Writes JSON data to an API.
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: 1,
title: 'Updated Title',
body: 'Updated content.',
userId: 1
}),
})
.then(res => res.json())
.then(console.log);
If an API endpoint supports DELETE requests, you can use fetch to execute a deletion request.
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'DELETE',
})
.then(res => {
if (res.ok) {
console.log('Successfully deleted');
} else {
throw new Error('Delete failed');
}
})
.catch(console.error);