Promise is an object in JavaScript representing the result of an asynchronous operation. It can be in one of three states: pending, fulfilled, or rejected. Promises simplify working with asynchronous code, eliminating “callback hell” and enabling chains of asynchronous operations.
Key benefits:
Promise is a fundamental concept of asynchronous programming in modern JavaScript. It represents an object that may produce a single value sometime in the future: either a resolved value or a reason why it wasn’t resolved (such as a network error).
A Promise can be in one of three states:
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
// Asynchronous operation
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation completed successfully');
} else {
reject('An error occurred');
}
}, 1000);
});
// Using Promise
myPromise
.then(result => console.log(result))
.catch(error => console.error(error));
Handles successful Promise resolution:
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Handles Promise rejection:
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
console.error('Error loading data:', error);
// Handle error
});
Executes regardless of the result:
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))
.finally(() => {
console.log('Request completed');
// Hide loading indicator
});
One of the main advantages of Promises is the ability to create chains:
// Chain of asynchronous operations
fetch('/api/user')
.then(response => response.json())
.then(user => fetch(`/api/profile/${user.id}`))
.then(response => response.json())
.then(profile => {
console.log('User profile:', profile);
return profile;
})
.catch(error => {
console.error('Error in chain:', error);
});
Executes multiple Promises in parallel:
const promises = [
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments')
];
Promise.all(promises)
.then(responses => Promise.all(responses.map(res => res.json())))
.then(([users, posts, comments]) => {
console.log('All data loaded:', { users, posts, comments });
})
.catch(error => {
console.error('Error loading data:', error);
});
Returns the result of the first completed Promise:
const promises = [
fetch('/api/fast-endpoint'),
fetch('/api/slow-endpoint')
];
Promise.race(promises)
.then(response => response.json())
.then(data => {
console.log('First response:', data);
});
Create already resolved or rejected Promises:
// Creating a resolved Promise
const resolvedPromise = Promise.resolve('Successful value');
// Creating a rejected Promise
const rejectedPromise = Promise.reject('Error');
resolvedPromise.then(value => console.log(value)); // 'Successful value'
rejectedPromise.catch(error => console.error(error)); // 'Error'
// Parallel loading of user data
async function loadUserProfile(userId) {
try {
const [user, posts, followers] = await Promise.all([
fetch(`/api/users/${userId}`).then(res => res.json()),
fetch(`/api/users/${userId}/posts`).then(res => res.json()),
fetch(`/api/users/${userId}/followers`).then(res => res.json())
]);
return { user, posts, followers };
} catch (error) {
console.error('Error loading profile:', error);
throw error;
}
}
// Function with callback
function readFileCallback(filename, callback) {
// Simulating asynchronous operation
setTimeout(() => {
if (filename) {
callback(null, `File content: ${filename}`);
} else {
callback('File not found', null);
}
}, 1000);
}
// Converting to Promise
function readFilePromise(filename) {
return new Promise((resolve, reject) => {
readFileCallback(filename, (error, data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
// Usage
readFilePromise('example.txt')
.then(data => console.log(data))
.catch(error => console.error(error));
// ❌ Bad - errors in chain may be lost
fetch('/api/data')
.then(response => response.json())
.then(data => {
throw new Error('Error processing data');
})
.then(processedData => console.log(processedData));
// ✅ Good - always add catch
fetch('/api/data')
.then(response => response.json())
.then(data => {
throw new Error('Error processing data');
})
.then(processedData => console.log(processedData))
.catch(error => console.error('Error:', error));
// ❌ Bad - value lost in chain
fetch('/api/user')
.then(response => response.json())
.then(user => {
// Forgot return
fetch(`/api/profile/${user.id}`).then(res => res.json());
})
.then(profile => {
// profile will be undefined
console.log(profile);
});
// ✅ Good - return Promise
fetch('/api/user')
.then(response => response.json())
.then(user => {
return fetch(`/api/profile/${user.id}`).then(res => res.json());
})
.then(profile => {
console.log(profile);
});
Promise is a powerful tool for working with asynchronous code in JavaScript. Understanding Promises allows you to create more readable, maintainable, and reliable code when working with network requests, timers, and other asynchronous operations.
Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪