Fetching Data from APIs in Modern JavaScript Modern web applications communicate with backend servers and cloud microservices through RESTful APIs and GraphQL endpoints. The modern standard for performing HTTP network requests in browsers and modern Node.js runtimes is the Fetch API .
The fetch() global function initiates an HTTP request and returns a Promise that resolves to a Response object representing the response to the request.
1 async function loadUserData ( userId ) {
2 const url = ` https://jsonplaceholder.typicode.com/users/ ${ userId } ` ;
3
4 const response = await fetch ( url ) ;
5 console . log ( 'Response Status:' , response . status ) ; // e.g. 200, 404, 500
6 console . log ( 'Status Text:' , response . statusText ) ; // e.g. "OK", "Not Found"
7 console . log ( 'Headers:' , response . headers . get ( 'content-type' ) ) ;
8 }
Unlike legacy libraries like Axios, fetch() will NOT reject its Promise on HTTP error status codes (like 404 Not Found or 500 Internal Server Error) !
A fetch Promise only rejects if there is a fatal network error (DNS lookup failed, device offline, CORS failure).
1 HTTP 404 / 500 Response:
2 fetch() Promise ──► FULFILLED! (response.ok === false)
3
4 No Internet / DNS Failure:
5 fetch() Promise ──► REJECTED! (TypeError: Failed to fetch)
The Standard Production Pattern: Check response.ok response.ok is a built-in boolean that evaluates to true if the HTTP status code is in the range 200-299:
1 async function fetchSecureResource ( endpoint ) {
2 try {
3 const response = await fetch ( endpoint ) ;
4
5 // MUST CHECK response.ok!
6 if ( ! response . ok ) {
7 throw new Error ( ` HTTP Error ${ response . status } : ${ response . statusText } ` ) ;
8 }
9
10 const data = await response . json ( ) ;
11 return data ;
12 } catch ( error ) {
13 console . error ( 'Fetch operation failed:' , error . message ) ;
14 throw error ; // Re-throw or handle gracefully
15 }
16 }
The second argument to fetch() is an options configuration object:
1 const response = await fetch ( '/api/v1/articles' , {
2 method : 'GET' , // Default is GET
3 headers : {
4 'Accept' : 'application/json' ,
5 'Authorization' : 'Bearer YOUR_JWT_TOKEN'
6 } ,
7 cache : 'no-cache' , // Bypass browser cache
8 mode : 'cors' // Enable Cross-Origin Resource Sharing
9 } ) ;
Avoid indefinite hanging on slow mobile networks by providing a timeout signal:
1 async function fetchWithTimeout ( url , ms = 5000 ) {
2 try {
3 // Abort automatically if server doesn't respond within 5000ms
4 const response = await fetch ( url , {
5 signal : AbortSignal . timeout ( ms )
6 } ) ;
7
8 if ( ! response . ok ) throw new Error ( ` HTTP error: ${ response . status } ` ) ;
9 return await response . json ( ) ;
10 } catch ( err ) {
11 if ( err . name === 'TimeoutError' ) {
12 console . error ( ` Request timed out after ${ ms } ms! ` ) ;
13 } else {
14 console . error ( 'Network error:' , err ) ;
15 }
16 }
17 }
Interactive Quiz • Knowledge Check
Practice Quiz When does the Promise returned by fetch() reject?
A When the server returns a 404 Not Found
B When the server returns a 500 Internal Server Error
C Only when there is an actual network failure (e.g., offline, DNS resolution failed)
D Whenever response.ok is false
What property on the Response object should you check to verify if an HTTP request succeeded with a 2xx status code?
A response.success
B response.statusValid
C response.ok
D response.is200
What is the default HTTP method used by fetch() when no options object is provided?
Which modern Web API method provides a clean way to automatically cancel a fetch request after a specified timeout?
A window.setTimeoutCancel()
B AbortSignal.timeout(ms)
C fetch.cancelAfter(ms)
D Promise.raceTimeout()
If a server returns an HTTP 500 status code, what does response.ok evaluate to?
A true
B false
C null
D undefined