How to Use Promises in JavaScript
Learn how to handle asynchronous operations in JavaScript using Promises.
Promises represent the eventual completion or failure of an asynchronous operation. They’re fundamental to modern JavaScript.
Creating a Promise
const myPromise = new Promise((resolve, reject) => {
// Async operation
const success = true;
if (success) {
resolve("Operation succeeded!");
} else {
reject("Operation failed!");
}
});
Using then() and catch()
myPromise
.then(result => {
console.log(result); // "Operation succeeded!"
})
.catch(error => {
console.error(error);
});
Promise States
A Promise has three states:
- Pending: Initial state, neither fulfilled nor rejected
- Fulfilled: Operation completed successfully
- Rejected: Operation failed
const pending = new Promise(() => {}); // Stays pending
const fulfilled = Promise.resolve("Done");
const rejected = Promise.reject("Error");
Chaining Promises
fetch('/api/user')
.then(response => response.json())
.then(user => fetch(`/api/posts/${user.id}`))
.then(response => response.json())
.then(posts => {
console.log(posts);
})
.catch(error => {
console.error("Error:", error);
});
Returning Values in Chains
Promise.resolve(1)
.then(value => value + 1) // Returns 2
.then(value => value * 2) // Returns 4
.then(value => {
console.log(value); // 4
});
Error Handling
catch() Method
fetch('/api/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error("Caught:", error));
finally() Method
let isLoading = true;
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))
.finally(() => {
isLoading = false; // Always runs
});
Promise.all()
Wait for all promises to complete:
const promise1 = fetch('/api/users').then(r => r.json());
const promise2 = fetch('/api/posts').then(r => r.json());
const promise3 = fetch('/api/comments').then(r => r.json());
Promise.all([promise1, promise2, promise3])
.then(([users, posts, comments]) => {
console.log(users, posts, comments);
})
.catch(error => {
// Fails fast: rejects if ANY promise rejects
console.error("One failed:", error);
});
Promise.allSettled()
Wait for all to settle (fulfill or reject):
const promises = [
Promise.resolve("Success 1"),
Promise.reject("Error"),
Promise.resolve("Success 2")
];
Promise.allSettled(promises)
.then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log("Value:", result.value);
} else {
console.log("Reason:", result.reason);
}
});
});
// Value: Success 1
// Reason: Error
// Value: Success 2
Promise.race()
Returns when the first promise settles:
const fast = new Promise(resolve =>
setTimeout(() => resolve("Fast"), 100)
);
const slow = new Promise(resolve =>
setTimeout(() => resolve("Slow"), 500)
);
Promise.race([fast, slow])
.then(result => {
console.log(result); // "Fast"
});
Promise.any()
Returns when the first promise fulfills:
const promises = [
Promise.reject("Error 1"),
Promise.resolve("Success"),
Promise.reject("Error 2")
];
Promise.any(promises)
.then(result => {
console.log(result); // "Success"
})
.catch(errors => {
// Only if ALL reject
console.log(errors);
});
Creating Utility Functions
Delay Function
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Usage
delay(2000).then(() => console.log("2 seconds passed"));
Timeout Wrapper
function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), ms)
);
return Promise.race([promise, timeout]);
}
// Usage
withTimeout(fetch('/api/data'), 5000)
.then(response => response.json())
.catch(error => console.error(error));
Retry Logic
function retry(fn, retries = 3, delay = 1000) {
return fn().catch(error => {
if (retries > 0) {
return new Promise(resolve =>
setTimeout(resolve, delay)
).then(() => retry(fn, retries - 1, delay));
}
throw error;
});
}
// Usage
retry(() => fetch('/api/data'), 3)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error("All retries failed"));
Converting Callbacks to Promises
// Callback-based function
function readFileCallback(path, callback) {
// callback(error, data)
}
// Promisified version
function readFilePromise(path) {
return new Promise((resolve, reject) => {
readFileCallback(path, (error, data) => {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
// Usage
readFilePromise('/path/to/file')
.then(data => console.log(data))
.catch(error => console.error(error));
Summary
- Create with
new Promise((resolve, reject) => {}) - Handle success with
.then() - Handle errors with
.catch() - Clean up with
.finally() Promise.all()- wait for all, fail fastPromise.allSettled()- wait for all to settlePromise.race()- first to settle winsPromise.any()- first to fulfill wins