How to Get the Value of a Promise in JavaScript
A Promise in JavaScript is an object that represents the eventual completion (or failure) of an asynchronous operation. A common challenge for developers is understanding how to "get the value out" of a promise, as you cannot access it directly. The key is to use mechanisms that wait for the promise to resolve.
This guide will teach you the two standard methods for accessing a promise's resolved value. We will cover the modern and highly recommended async/await syntax, as well as the classic .then() method for promise chaining.
The Core Concept: Promises are Asynchronous
You cannot get the value of a promise synchronously. A promise exists in one of three states:
- Pending: The initial state; the asynchronous operation has not yet completed.
- Fulfilled: The operation completed successfully, and the promise now has a resolved value.
- Rejected: The operation failed, and the promise has a reason for the failure.
You can only access the value after the promise is fulfilled.
For example: how do we get the string 'Success!' from this promise?
// Problem: How do we get the string 'Success!' from this promise?
const myPromise = new Promise((resolve) => {
setTimeout(() => {
resolve('Success!');
}, 1000);
});
// ⛔️ This does NOT work. It will log the pending Promise object itself.
console.log(myPromise);
The Modern Method (Recommended): async/await
The async/await syntax is the modern standard for working with promises. It provides a way to write asynchronous code that looks and behaves like synchronous code, making it much easier to read and reason about.
The logic:
- Mark the function that contains the promise as
async. - Use the
awaitkeyword in front of the promise. This will pause the execution of your function until the promise is fulfilled. - The
awaitexpression then returns the promise's resolved value.
Solution:
const myPromise = Promise.resolve('Success!'); // A simple fulfilled promise
// 1. Declare the function as `async`
async function getValue() {
// 2. `await` the promise
const resolvedValue = await myPromise;
console.log(resolvedValue);
}
getValue();
Output:
Success!
How to Handle Errors with async/await
If a promise is rejected, the await expression will throw an error. The standard way to handle this is with a try...catch block.
const rejectedPromise = Promise.reject('Something went wrong!');
async function handleRejection() {
try {
const value = await rejectedPromise;
console.log(value); // This line will not be reached
} catch (error) {
// The catch block will execute if the promise is rejected.
console.error('Caught an error:', error);
}
}
handleRejection();
Output:
Caught an error: Something went wrong!
This is the recommended best practice for its clarity and for handling both success and error cases in a familiar structure.
The Classic Method: .then() and .catch()
The original way to work with promises is by chaining the .then() and .catch() methods.
.then(callback): Takes a callback function that will be executed when the promise is fulfilled. The resolved value is passed as the first argument to this callback..catch(callback): Takes a callback function that will be executed when the promise is rejected. The rejection reason (error) is passed to its callback.
Solution:
const myPromise = Promise.resolve('Success!');
myPromise
.then(resolvedValue => {
// This code runs when the promise is fulfilled.
console.log(resolvedValue); // Output: "Success!"
})
.catch(error => {
// This code runs if the promise is rejected.
console.error(error);
});
While this is perfectly functional, async/await is generally considered more readable, especially when you need to handle multiple asynchronous operations in sequence.
Conclusion
You can never access the value of a promise synchronously. You must use an asynchronous pattern to wait for it to resolve.
- The
async/awaitsyntax is the recommended best practice. It is modern, highly readable, and allows you to write asynchronous code that looks synchronous, with standardtry...catcherror handling. - The
.then()and.catch()methods are the classic way to handle promises. They are still widely used and are essential for understanding promise chaining.
For most new code, async/await provides the cleanest and most maintainable solution for working with promises.