Chapter 20 Advanced 50 Questions

Practice Questions — Fetch API - Getting Data from the Internet

← Back to Notes
9 Easy
8 Medium
5 Hard

Topic-Specific Questions

Question 1
Easy
What does response.ok return when the server responds with status 200?
ok is true for status codes 200-299.
true
Question 2
Easy
What does response.ok return when the server responds with status 404?
404 means Not Found.
false
Question 3
Easy
What is the output?
const obj = { name: "Aarav", age: 16 };
const json = JSON.stringify(obj);
console.log(typeof json);
console.log(json);
JSON.stringify converts an object to a JSON string.
string
{"name":"Aarav","age":16}
Question 4
Easy
What is the output?
const json = '{"name":"Priya","score":95}';
const obj = JSON.parse(json);
console.log(obj.name);
console.log(obj.score + 5);
JSON.parse converts a JSON string to a JavaScript object.
Priya
100
Question 5
Easy
What is the output?
const users = [
  { name: "Aarav", city: "Delhi" },
  { name: "Priya", city: "Mumbai" }
];

users.forEach(function(user) {
  console.log(user.name + " from " + user.city);
});
forEach iterates through each user object.
Aarav from Delhi
Priya from Mumbai
Question 6
Easy
Why do we need to call response.json() after fetch()? Why does fetch not give us the JSON directly?
The response body can be different formats.
The fetch Response object contains the HTTP response metadata (status, headers) and a body stream. The body could be JSON, text, a blob (image), or other formats. response.json() reads the body stream and parses it as JSON. response.text() reads it as plain text. You choose the parsing method based on what the API returns.
Question 7
Medium
What is the output?
async function test() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
  console.log(typeof response);
  console.log(response.ok);
  console.log(response.status);
}
test();
fetch returns a Response object. jsonplaceholder returns 200 for valid IDs.
object
true
200
Question 8
Medium
What is the output?
const data = [
  { id: 1, name: "Post 1" },
  { id: 2, name: "Post 2" },
  { id: 3, name: "Post 3" }
];

const filtered = data.filter(item => item.id > 1);
console.log(filtered.length);
console.log(filtered.map(item => item.name));
filter keeps items where id > 1. map extracts names.
2
["Post 2", "Post 3"]
Question 9
Medium
What is CORS and why does it block some API requests?
Think about security between different websites.
CORS (Cross-Origin Resource Sharing) is a browser security feature that prevents web pages from making requests to a different domain unless the server explicitly allows it. When your page at mysite.com tries to fetch from api.other.com, the browser checks if the API server includes the Access-Control-Allow-Origin header. If not, the request is blocked. CORS prevents malicious websites from making requests to APIs on behalf of unsuspecting users.
Question 10
Hard
What is the output?
async function fetchTwo() {
  const [users, posts] = await Promise.all([
    fetch("https://jsonplaceholder.typicode.com/users").then(r => r.json()),
    fetch("https://jsonplaceholder.typicode.com/posts").then(r => r.json())
  ]);

  console.log("Users:", users.length);
  console.log("Posts:", posts.length);
}

fetchTwo();
jsonplaceholder has 10 users and 100 posts.
Users: 10
Posts: 100
Question 11
Hard
Why is it important to check response.ok before calling response.json()?
What happens if the server returns a 404 or 500 error?
If the server returns a 404 or 500, the response body might be an HTML error page, not JSON. Calling response.json() on HTML will throw a SyntaxError because it is not valid JSON. Also, even if the error response IS JSON (some APIs return JSON error objects), you should handle it differently from success data. Checking response.ok first lets you throw a meaningful error before attempting to parse.
Question 12
Medium
What is the output?
const obj = { name: "Aarav", age: 16 };
const json = JSON.stringify(obj);
const parsed = JSON.parse(json);
console.log(parsed.name);
console.log(obj === parsed);
JSON.stringify then JSON.parse creates a new object.
Aarav
false
Question 13
Easy
What is the output?
const data = [1, 2, 3, 4, 5];
const filtered = data.filter(n => n > 3);
console.log(filtered);
filter keeps elements where the condition is true.
[4, 5]

Mixed & Application Questions

Question 1
Easy
What is the output?
const arr = [10, 20, 30];
const doubled = arr.map(x => x * 2);
console.log(doubled);
map creates a new array by applying a function to each element.
[20, 40, 60]
Question 2
Easy
What is the output?
const user = { name: "Diya", address: { city: "Pune" } };
console.log(user.address.city);
console.log(user.phone?.number ?? "N/A");
Optional chaining and nullish coalescing for missing properties.
Pune
N/A
Question 3
Medium
What is the output?
async function getData() {
  return { name: "Aarav" };
}

const result = getData();
console.log(result);
console.log(result.name);
async functions always return a Promise.
Promise { { name: 'Aarav' } }
undefined
Question 4
Medium
What is the output?
const users = [
  { name: "Aarav", active: true },
  { name: "Priya", active: false },
  { name: "Rohan", active: true }
];

const active = users.filter(u => u.active).map(u => u.name);
console.log(active);
filter keeps active users, map extracts names.
["Aarav", "Rohan"]
Question 5
Medium
What is the output?
try {
  const obj = JSON.parse("not json");
} catch (error) {
  console.log(error.name);
}

try {
  const obj = JSON.parse('{"name": "Aarav"}');
  console.log(obj.name);
} catch (error) {
  console.log("Error");
}
First parse fails (SyntaxError). Second parse succeeds.
SyntaxError
Aarav
Question 6
Hard
What is the output?
async function fetchUser() {
  // Simulating fetch
  return { name: "Aarav", scores: [85, 92, 78] };
}

async function main() {
  const user = await fetchUser();
  const { name, scores } = user;
  const avg = scores.reduce((sum, s) => sum + s, 0) / scores.length;
  console.log(name + ": " + avg.toFixed(1));
}

main();
Destructure the user, then calculate average of scores.
Aarav: 85.0
Question 7
Hard
What is the output?
async function fetchWithRetry(url, retries) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error("HTTP " + response.status);
      return await response.json();
    } catch (error) {
      console.log("Attempt " + (i + 1) + " failed: " + error.message);
      if (i === retries - 1) throw error;
    }
  }
}

// Assuming all 3 attempts fail with 404
fetchWithRetry("https://jsonplaceholder.typicode.com/users/9999", 3)
  .catch(e => console.log("Final: " + e.message));
User 9999 does not exist (404). All 3 attempts will fail.
Attempt 1 failed: HTTP 404
Attempt 2 failed: HTTP 404
Attempt 3 failed: HTTP 404
Final: HTTP 404
Question 8
Medium
What is the difference between response.json() and JSON.parse()?
One works with a Response stream, the other with a string.
response.json() reads the Response body stream and parses it as JSON. It returns a Promise because reading the stream is async. JSON.parse() takes a plain string and parses it synchronously. You cannot call JSON.parse on a Response object, and you cannot call .json() on a string.
Question 9
Hard
When building a search feature that fetches from an API on every keystroke, what problems can occur and how do you solve them?
Think about too many requests and out-of-order responses.
Two main problems: (1) Too many requests: typing 'Delhi' sends 5 requests (D, De, Del, Delh, Delhi). Solution: debouncing -- wait 300-500ms after the last keystroke before fetching. (2) Out-of-order responses: the request for 'De' might return after the request for 'Delhi', replacing correct results with stale ones. Solution: store the latest search term and ignore responses for outdated queries, or use AbortController to cancel previous requests.

Multiple Choice Questions

MCQ 1
What does the Fetch API return?
  • A. JSON data directly
  • B. A Promise that resolves to a Response object
  • C. An HTML page
  • D. A string
Answer: B
B is correct. fetch() returns a Promise. That Promise resolves to a Response object. You then call response.json() to get the actual data.
MCQ 2
Which method parses a fetch Response body as JSON?
  • A. response.parse()
  • B. response.toJSON()
  • C. response.json()
  • D. JSON.parse(response)
Answer: C
C is correct. response.json() reads the response body and parses it as JSON. It returns a Promise. Option D does not work because Response is not a string.
MCQ 3
What does API stand for?
  • A. Advanced Programming Interface
  • B. Application Programming Interface
  • C. Automated Processing Integration
  • D. Application Protocol Interface
Answer: B
B is correct. API stands for Application Programming Interface. It defines how different software systems communicate with each other.
MCQ 4
What format do most web APIs return data in?
  • A. HTML
  • B. XML
  • C. JSON
  • D. CSV
Answer: C
C is correct. JSON (JavaScript Object Notation) is the standard data format for web APIs. It is lightweight, human-readable, and natively supported by JavaScript.
MCQ 5
What status code means 'success' in HTTP?
  • A. 100
  • B. 200
  • C. 404
  • D. 500
Answer: B
B is correct. 200 means 'OK' (success). 100 is informational. 404 is Not Found. 500 is Internal Server Error.
MCQ 6
Does fetch() reject its Promise when the server returns a 404 error?
  • A. Yes, all errors cause rejection
  • B. No, it only rejects on network failures (not HTTP errors)
  • C. It depends on the server
  • D. Yes, but only for 500 errors
Answer: B
B is correct. fetch only rejects on network failures (server unreachable, no internet). HTTP error responses (404, 500) still resolve the Promise. You must check response.ok to detect HTTP errors.
MCQ 7
What must you include in the body of a POST request when sending JSON data?
  • A. The JavaScript object directly
  • B. JSON.stringify(data)
  • C. data.toString()
  • D. new JSON(data)
Answer: B
B is correct. The body must be a string. JSON.stringify() converts a JavaScript object to a JSON string. Sending the object directly would result in '[object Object]'.
MCQ 8
What header tells the server the format of the data you are sending?
  • A. Accept
  • B. Data-Format
  • C. Content-Type
  • D. Body-Format
Answer: C
C is correct. Content-Type: application/json tells the server that the request body is JSON. Accept tells the server what format you want in the response.
MCQ 9
What is the purpose of a loading state in a fetch-based UI?
  • A. To slow down the request
  • B. To give users visual feedback that data is being loaded
  • C. To prevent errors
  • D. To cache the data
Answer: B
B is correct. Loading states (spinners, 'Loading...' text) tell users that something is happening. Without them, users might think the app is frozen or click buttons multiple times.
MCQ 10
What is CORS?
  • A. A JavaScript framework
  • B. A way to compress data
  • C. A browser security feature that restricts cross-origin HTTP requests
  • D. A type of API authentication
Answer: C
C is correct. CORS (Cross-Origin Resource Sharing) prevents web pages from making requests to different domains unless the server explicitly allows it. It protects users from malicious cross-site requests.
MCQ 11
Why should you use Promise.all when fetching multiple independent API endpoints?
  • A. It is required by the Fetch API
  • B. It runs requests in parallel, reducing total load time
  • C. It handles errors automatically
  • D. It caches the responses
Answer: B
B is correct. Promise.all starts all requests simultaneously. Five 200ms requests take ~200ms total with Promise.all, but ~1000ms if awaited sequentially.
MCQ 12
What does response.status contain?
  • A. A boolean (true/false)
  • B. The HTTP status code number (200, 404, 500, etc.)
  • C. The response body
  • D. The URL of the request
Answer: B
B is correct. response.status is the numeric HTTP status code. 200 = OK, 201 = Created, 404 = Not Found, 500 = Server Error. response.ok is the boolean (true for 200-299).
MCQ 13
What is debouncing in the context of a search feature?
  • A. Making the search faster
  • B. Waiting for the user to stop typing before sending the request
  • C. Caching previous search results
  • D. Sending multiple requests at once
Answer: B
B is correct. Debouncing delays the API call until the user stops typing (e.g., 300ms after the last keystroke). This prevents sending a request for every single character typed.
MCQ 14
What does JSON.stringify() do?
  • A. Parses a JSON string into an object
  • B. Converts a JavaScript object into a JSON string
  • C. Validates if a string is JSON
  • D. Compresses JSON data
Answer: B
B is correct. JSON.stringify converts a JavaScript object or array into a JSON-formatted string. This is needed when sending data in a POST request body.
MCQ 15
What HTTP method is used to send new data to a server?
  • A. GET
  • B. POST
  • C. FETCH
  • D. SEND
Answer: B
B is correct. POST is used to send data to a server to create a new resource. GET is for retrieving data. FETCH and SEND are not HTTP methods.
MCQ 16
What does response.json() return?
  • A. A JavaScript object directly
  • B. A JSON string
  • C. A Promise that resolves to a JavaScript object
  • D. The response headers
Answer: C
C is correct. response.json() reads the response body stream and parses it as JSON. Because reading the stream is asynchronous, it returns a Promise. You need await response.json().
MCQ 17
What status code means 'Not Found'?
  • A. 200
  • B. 301
  • C. 404
  • D. 500
Answer: C
C is correct. 404 means the requested resource was not found on the server. 200 is success, 301 is redirect, 500 is server error.
MCQ 18
What is response.statusText for a 404 response?
  • A. "Error"
  • B. "Not Found"
  • C. "Failed"
  • D. "404"
Answer: B
B is correct. response.statusText contains the human-readable status message. For 404, it is 'Not Found'. For 200, it is 'OK'. For 500, it is 'Internal Server Error'.
MCQ 19
Why might you get a CORS error when fetching from localhost to an external API?
  • A. localhost cannot make network requests
  • B. The external API server does not include Access-Control-Allow-Origin header for your origin
  • C. fetch does not work on localhost
  • D. The browser is blocking all external requests
Answer: B
B is correct. CORS errors occur when the API server does not allow your origin (like http://localhost:3000). The server must include the Access-Control-Allow-Origin header to permit cross-origin requests.
MCQ 20
What is the default HTTP method when you call fetch(url) without options?
  • A. POST
  • B. PUT
  • C. GET
  • D. HEAD
Answer: C
C is correct. By default, fetch makes a GET request. You must explicitly set method: 'POST' in the options to make a POST request.

Coding Challenges

Challenge 1: Fetch and Display a User

Easy
Write an async function displayUser(id) that fetches a user from jsonplaceholder.typicode.com/users/{id} and logs their name, email, and city.
Sample Input
displayUser(1)
Sample Output
Name: Leanne Graham Email: Sincere@april.biz City: Gwenborough
Use async/await. Handle errors with try-catch.
async function displayUser(id) {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users/' + id);
    if (!response.ok) throw new Error('User not found');
    const user = await response.json();
    console.log('Name:', user.name);
    console.log('Email:', user.email);
    console.log('City:', user.address.city);
  } catch (error) {
    console.log('Error:', error.message);
  }
}

displayUser(1);

Challenge 2: Fetch Multiple Users

Easy
Write an async function getUserNames(ids) that takes an array of user IDs, fetches all users in parallel using Promise.all, and returns an array of their names.
Sample Input
[1, 2, 3]
Sample Output
["Leanne Graham", "Ervin Howell", "Clementine Bauch"]
Use Promise.all for parallel fetching. Return the names array.
async function getUserNames(ids) {
  const promises = ids.map(id =>
    fetch('https://jsonplaceholder.typicode.com/users/' + id)
      .then(r => r.json())
      .then(user => user.name)
  );
  return Promise.all(promises);
}

getUserNames([1, 2, 3]).then(names => console.log(names));

Challenge 3: Create a Post via API

Medium
Write an async function createPost(title, body) that sends a POST request to jsonplaceholder.typicode.com/posts with the title, body, and userId: 1. Log the created post's id and title.
Sample Input
createPost('My Post', 'Hello world')
Sample Output
Created post #101: My Post
Use method POST, Content-Type header, and JSON.stringify for the body.
async function createPost(title, body) {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ title, body, userId: 1 })
    });
    if (!response.ok) throw new Error('Failed to create');
    const post = await response.json();
    console.log('Created post #' + post.id + ': ' + post.title);
  } catch (error) {
    console.log('Error:', error.message);
  }
}

createPost('My Post', 'Hello world');

Challenge 4: Safe Fetch Wrapper

Medium
Write an async function safeFetch(url) that wraps fetch with proper error handling. It should return { ok: true, data } on success and { ok: false, error } on failure. Handle both network errors and HTTP errors.
Sample Input
safeFetch('https://jsonplaceholder.typicode.com/users/1')
Sample Output
{ ok: true, data: { id: 1, name: 'Leanne Graham', ... } }
Check response.ok. Use try-catch. Return a consistent object shape.
async function safeFetch(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      return { ok: false, error: 'HTTP ' + response.status + ': ' + response.statusText };
    }
    const data = await response.json();
    return { ok: true, data };
  } catch (error) {
    return { ok: false, error: error.message };
  }
}

async function demo() {
  const r1 = await safeFetch('https://jsonplaceholder.typicode.com/users/1');
  console.log(r1.ok ? r1.data.name : r1.error);

  const r2 = await safeFetch('https://jsonplaceholder.typicode.com/users/9999');
  console.log(r2.ok ? r2.data.name : r2.error);
}
demo();

Challenge 5: User Card Page with Loading and Error States

Medium
Build a complete page that fetches all users from jsonplaceholder.typicode.com/users and displays them as cards. Show 'Loading...' while fetching, user cards on success, and an error message on failure. Use proper error handling.
Sample Input
Page loads automatically
Sample Output
Loading... -> 10 user cards with name, email, and city
Show three states: loading, success, error. Use async/await and DOM manipulation.
// HTML: <div id="app"></div>

async function loadUsers() {
  const app = document.getElementById('app');
  app.innerHTML = '<p>Loading users...</p>';

  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) throw new Error('Failed: HTTP ' + response.status);
    const users = await response.json();

    app.innerHTML = '';
    users.forEach(user => {
      const card = document.createElement('div');
      card.style.cssText = 'background:#16213e;padding:16px;margin:8px;border-radius:8px;';
      card.innerHTML = '<h3>' + user.name + '</h3>' +
        '<p>Email: ' + user.email + '</p>' +
        '<p>City: ' + user.address.city + '</p>';
      app.appendChild(card);
    });
  } catch (error) {
    app.innerHTML = '<p style="color:#ef4444;">Error: ' + error.message + '</p>';
  }
}

loadUsers();

Challenge 6: Search Posts by Keyword

Hard
Fetch all posts from jsonplaceholder.typicode.com/posts. Write a function searchPosts(keyword) that filters posts where the title or body includes the keyword (case-insensitive). Display matching results.
Sample Input
searchPosts('sunt')
Sample Output
Found 5 posts containing 'sunt'
Fetch all posts once, then filter client-side. Use includes() for searching. Case-insensitive.
let allPosts = [];

async function loadPosts() {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  allPosts = await response.json();
  console.log('Loaded', allPosts.length, 'posts');
}

function searchPosts(keyword) {
  const kw = keyword.toLowerCase();
  const results = allPosts.filter(post =>
    post.title.toLowerCase().includes(kw) ||
    post.body.toLowerCase().includes(kw)
  );

  console.log('Found ' + results.length + " posts containing '" + keyword + "'");
  results.forEach(post => console.log(' - ' + post.title));
  return results;
}

async function main() {
  await loadPosts();
  searchPosts('sunt');
}
main();

Challenge 7: User Detail Page with Related Posts

Hard
Fetch a user by ID and their posts in parallel (both from jsonplaceholder). Display the user's name and email, followed by a list of their post titles.
Sample Input
loadUserPage(1)
Sample Output
User: Leanne Graham (Sincere@april.biz) Posts (10): - sunt aut facere... - qui est esse...
Use Promise.all for parallel fetching. Users at /users/{id}, posts at /posts?userId={id}.
async function loadUserPage(userId) {
  try {
    const [user, posts] = await Promise.all([
      fetch('https://jsonplaceholder.typicode.com/users/' + userId).then(r => r.json()),
      fetch('https://jsonplaceholder.typicode.com/posts?userId=' + userId).then(r => r.json())
    ]);

    console.log('User:', user.name, '(' + user.email + ')');
    console.log('Posts (' + posts.length + '):');
    posts.forEach(post => console.log(' - ' + post.title));
  } catch (error) {
    console.log('Error:', error.message);
  }
}

loadUserPage(1);

Challenge 8: API Data Cache

Hard
Build a cachedFetch(url) function that caches responses. If the same URL is requested again, return the cached data instead of making a new network request. Log whether the data came from cache or network.
Sample Input
cachedFetch('/users/1') twice
Sample Output
First call: [network] fetched /users/1 Second call: [cache] returned /users/1
Use a Map or object as cache. Return cached data if available.
const cache = new Map();

async function cachedFetch(url) {
  if (cache.has(url)) {
    console.log('[cache] returned', url);
    return cache.get(url);
  }

  const response = await fetch(url);
  if (!response.ok) throw new Error('HTTP ' + response.status);
  const data = await response.json();

  cache.set(url, data);
  console.log('[network] fetched', url);
  return data;
}

async function demo() {
  const user1 = await cachedFetch('https://jsonplaceholder.typicode.com/users/1');
  console.log(user1.name);

  const user1again = await cachedFetch('https://jsonplaceholder.typicode.com/users/1');
  console.log(user1again.name);

  console.log('Cache size:', cache.size);
}
demo();

Need to Review the Concepts?

Go back to the detailed notes for this chapter.

Read Chapter Notes

Want to learn web development with a live mentor?

Explore our Frontend Masterclass