[React][API] The Promise You See on Every API Call
Why fetch returns Promise { <pending> }, the three Promise states, and how .then / .catch / .finally map to real API success and failure - plus how async/await sits on top.

1. Environment
- OS: Windows 11 / macOS
- Language: JavaScript (ES6+)
- Frontend library: React.js
- IDE: Visual Studio Code (VS Code)
2. Problem
If you have called a server API from JavaScript or React, you have probably seen this odd console value: Promise { <pending> }.
Earlier posts cover async / await for browser async work. The backbone of that syntax - and the real star of JavaScript async - is the Promise.
3. Cause
JavaScript does not patiently freeze until the server answers.
Instead it hands you a “I will notify you when the data arrives|–voucher and continues with the next lines. That voucher is a Promise.
// Common mistake
const userData = fetch('https://api.example.com/user');
console.log(userData);
// Expected: { name: "Hong Gildong", age: 20 }
// Actual: Promise { <pending> }
4. Solution
1) Promise as a vibrating pager
Think of a Promise as a future result ticket for work that is not finished yet.
- Order (API call): The client orders an Americano.
- Promise issued: The server gives a vibrating pager (Promise), not the coffee yet - so the client can do other work.
- Fulfilled: The pager buzzes; you get the coffee (data).
- Rejected: The machine fails; you get a refund (error message).
2) Three Promise states
| State | Meaning |
|---|---|
| Pending | Waiting with the pager - work not finished |
| Fulfilled | Success - data arrived |
| Rejected | Failure - error occurred |
3) Controlling a Promise (.then / .catch / .finally)
fetch() is a classic function that returns a Promise (the pager):
fetch('https://api.example.com/user')
// 1. Success (Fulfilled): .then()
.then((response) => {
console.log('Request succeeded!');
return response.json(); // pass parsed data to the next then
})
.then((data) => {
console.log('User data:', data);
})
// 2. Failure (Rejected): .catch()
// 404, offline drop, etc.
.catch((error) => {
console.error('Server problem!', error);
})
// 3. Always runs: .finally()
// Great for turning off a loading spinner
.finally(() => {
console.log('Request finished. Clear loading state.');
});
5. Summary
A Promise during server I/O is JavaScript?’s note: “Data is coming - wait a moment.|–
You mainly decide what to do when the pager succeeds (.then) or fails (.catch).
If chaining .then().catch() feels noisy, async / await is the newer style that reads as “stand here until the pager buzzes” - built on the same Promise foundation.


