Skip to content

JavaScript/Fetch Examples

This page contains comprehensive examples of using the JSONPlaceholder API with JavaScript and the modern Fetch API.

Basic Setup

Choose the appropriate base URL for your use case:

javascript
const BASE_URL = 'https://api.jsonplaceholder.dev';

// Helper function for API calls
async function apiCall(endpoint, options = {}) {
  const url = `${BASE_URL}${endpoint}`;
  const config = {
    headers: {
      'Content-Type': 'application/json',
      ...options.headers
    },
    ...options
  };

  try {
    const response = await fetch(url, config);
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
}
javascript
const BASE_URL = 'http://localhost:3000';

// Helper function for API calls
async function apiCall(endpoint, options = {}) {
  const url = `${BASE_URL}${endpoint}`;
  const config = {
    headers: {
      'Content-Type': 'application/json',
      ...options.headers
    },
    ...options
  };

  try {
    const response = await fetch(url, config);
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    
    return await response.json();
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
}

Users Examples

Get All Users

javascript
async function getAllUsers() {
  try {
    const users = await fetch(`${BASE_URL}/users`);
    const userData = await users.json();
    console.log('All users:', userData);
    return userData;
  } catch (error) {
    console.error('Error fetching users:', error);
  }
}

Get User by ID

javascript
async function getUserById(userId) {
  try {
    const user = await apiCall(`/users/${userId}`);
    console.log('User details:', user);
    return user;
  } catch (error) {
    console.error(`Error fetching user ${userId}:`, error);
  }
}

Create New User

javascript
async function createUser(userData) {
  try {
    const newUser = await apiCall('/users', {
      method: 'POST',
      body: JSON.stringify({
        name: userData.name,
        username: userData.username,
        email: userData.email,
        address: {
          street: userData.address?.street || '123 Main St',
          city: userData.address?.city || 'New York',
          zipcode: userData.address?.zipcode || '10001'
        },
        phone: userData.phone || '1-555-123-4567',
        website: userData.website || 'example.com'
      })
    });
    
    console.log('Created user:', newUser);
    return newUser;
  } catch (error) {
    console.error('Error creating user:', error);
  }
}

### Update User

```javascript
async function updateUser(userId, updates) {
  const updatedUser = await apiCall(`/users/${userId}`, {
    method: 'PUT',
    body: JSON.stringify({
      id: userId,
      name: updates.name,
      username: updates.username,
      email: updates.email,
      ...updates
    })
  });
  
  console.log('Updated user:', updatedUser);
  return updatedUser;
}

// Partial update with PATCH
async function patchUser(userId, updates) {
  const patchedUser = await apiCall(`/users/${userId}`, {
    method: 'PATCH',
    body: JSON.stringify(updates)
  });
  
  console.log('Patched user:', patchedUser);
  return patchedUser;
}

### Delete User

```javascript
async function deleteUser(userId) {
  try {
    await apiCall(`/users/${userId}`, {
      method: 'DELETE'
    });
    
    console.log(`User ${userId} deleted successfully`);
    return true;
  } catch (error) {
    console.error(`Error deleting user ${userId}:`, error);
    return false;
  }
}

// Usage createUser({ name: 'John Doe', username: 'johndoe', email: '[email protected]' });

// Update examples updateUser(1, { name: 'John Doe Updated', email: '[email protected]' }); patchUser(1, { email: '[email protected]' }); deleteUser(1);


## Posts Examples

### Get All Posts

```javascript
async function getAllPosts() {
  const posts = await apiCall('/posts');
  console.log(`Fetched ${posts.length} posts`);
  return posts;
}

Get Posts by User

javascript
async function getPostsByUser(userId) {
  const posts = await apiCall(`/posts?userId=${userId}`);
  console.log(`User ${userId} has ${posts.length} posts`);
  return posts;
}

Create New Post

javascript
async function createPost(postData) {
  const newPost = await apiCall('/posts', {
    method: 'POST',
    body: JSON.stringify({
      userId: postData.userId,
      title: postData.title,
      body: postData.body
    })
  });
  
  console.log('Created post:', newPost);
  return newPost;
}

// Usage
createPost({
  userId: 1,
  title: 'My First Post',
  body: 'This is the content of my first post!'
});

Update Post

javascript
async function updatePost(postId, updates) {
  const updatedPost = await apiCall(`/posts/${postId}`, {
    method: 'PATCH',
    body: JSON.stringify(updates)
  });
  
  console.log('Updated post:', updatedPost);
  return updatedPost;
}

// Usage
updatePost(1, { title: 'Updated Title' });

Comments Examples

Get Comments for a Post

javascript
async function getPostComments(postId) {
  const comments = await apiCall(`/posts/${postId}/comments`);
  console.log(`Post ${postId} has ${comments.length} comments`);
  return comments;
}

Add Comment to Post

javascript
async function addComment(postId, commentData) {
  const comment = await apiCall('/comments', {
    method: 'POST',
    body: JSON.stringify({
      postId: postId,
      name: commentData.name,
      email: commentData.email,
      body: commentData.body
    })
  });
  
  console.log('Added comment:', comment);
  return comment;
}

// Usage
addComment(1, {
  name: 'Great post!',
  email: '[email protected]',
  body: 'Thanks for sharing this information!'
});

Advanced Examples

Async/Await with Error Handling

javascript
class JSONPlaceholderAPI {
  constructor(baseUrl = 'http://localhost:3000') {
    this.baseUrl = baseUrl;
  }

  async request(endpoint, options = {}) {
    const url = `${this.baseUrl}${endpoint}`;
    const config = {
      headers: {
        'Content-Type': 'application/json',
      },
      ...options
    };

    try {
      const response = await fetch(url, config);
      
      if (!response.ok) {
        throw new Error(`${response.status}: ${response.statusText}`);
      }
      
      return await response.json();
    } catch (error) {
      console.error(`API Error for ${endpoint}:`, error.message);
      throw error;
    }
  }

  // Users
  getUsers() {
    return this.request('/users');
  }

  getUser(id) {
    return this.request(`/users/${id}`);
  }

  getUserPosts(id) {
    return this.request(`/users/${id}/posts`);
  }

  // Posts
  getPosts(userId = null) {
    const endpoint = userId ? `/posts?userId=${userId}` : '/posts';
    return this.request(endpoint);
  }

  createPost(postData) {
    return this.request('/posts', {
      method: 'POST',
      body: JSON.stringify(postData)
    });
  }

  // Comments
  getComments(postId = null) {
    const endpoint = postId ? `/comments?postId=${postId}` : '/comments';
    return this.request(endpoint);
  }
}

// Usage
const api = new JSONPlaceholderAPI();

async function example() {
  try {
    const users = await api.getUsers();
    const firstUser = users[0];
    console.log('First user:', firstUser);
    
    const userPosts = await api.getUserPosts(firstUser.id);
    console.log(`${firstUser.name} has ${userPosts.length} posts`);
    
  } catch (error) {
    console.error('Example failed:', error);
  }
}

example();

Batch Operations

javascript
async function batchCreatePosts(posts) {
  const promises = posts.map(post => apiCall('/posts', {
    method: 'POST',
    body: JSON.stringify(post)
  }));
  
  try {
    const results = await Promise.all(promises);
    console.log(`Successfully created ${results.length} posts`);
    return results;
  } catch (error) {
    console.error('Batch create failed:', error);
  }
}

// Usage
const postsToCreate = [
  { userId: 1, title: 'Post 1', body: 'Content 1' },
  { userId: 1, title: 'Post 2', body: 'Content 2' },
  { userId: 2, title: 'Post 3', body: 'Content 3' }
];

batchCreatePosts(postsToCreate);

Real-time Data Fetching

javascript
class LiveDataFetcher {
  constructor(apiUrl) {
    this.apiUrl = apiUrl;
    this.cache = new Map();
    this.cacheTimeout = 30000; // 30 seconds
  }

  async fetchWithCache(endpoint) {
    const cacheKey = endpoint;
    const cached = this.cache.get(cacheKey);
    
    if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
      console.log('Returning cached data for:', endpoint);
      return cached.data;
    }

    try {
      const data = await apiCall(endpoint);
      this.cache.set(cacheKey, {
        data,
        timestamp: Date.now()
      });
      return data;
    } catch (error) {
      // Return cached data if available, even if expired
      if (cached) {
        console.log('Returning expired cached data due to error');
        return cached.data;
      }
      throw error;
    }
  }

  async getLiveUserData(userId) {
    const [user, posts, albums, todos] = await Promise.all([
      this.fetchWithCache(`/users/${userId}`),
      this.fetchWithCache(`/users/${userId}/posts`),
      this.fetchWithCache(`/users/${userId}/albums`),
      this.fetchWithCache(`/users/${userId}/todos`)
    ]);

    return {
      user,
      stats: {
        postsCount: posts.length,
        albumsCount: albums.length,
        todosCount: todos.length,
        completedTodos: todos.filter(t => t.completed).length
      }
    };
  }
}

// Usage
const liveData = new LiveDataFetcher();
liveData.getLiveUserData(1).then(userData => {
  console.log('Live user data:', userData);
});

Admin Operations

Reset All Data

javascript
async function resetAllData() {
  try {
    const result = await apiCall('/reset', {
      method: 'POST'
    });
    
    console.log('Data reset successful:', result);
    return result;
  } catch (error) {
    console.error('Reset failed:', error);
    // Note: This will fail if ENABLE_UPDATES=0
    throw error;
  }
}

// Usage - only works when server has ENABLE_UPDATES=1
resetAllData().then(result => {
  console.log('Reset completed at:', result.timestamp);
}).catch(error => {
  console.log('Reset not available - server may be in read-only mode');
});

// Check if reset worked by getting fresh data
async function verifyReset() {
  try {
    await resetAllData();
    
    // Verify by checking user count
    const users = await apiCall('/users');
    console.log(`Reset successful - ${users.length} users restored`);
    
    return true;
  } catch (error) {
    console.log('Reset verification failed:', error.message);
    return false;
  }
}

Important: The reset endpoint only works when the server is running with ENABLE_UPDATES=1. In read-only mode (ENABLE_UPDATES=0), this endpoint will return an error.

Error Handling Patterns

Retry Logic

javascript
async function apiCallWithRetry(endpoint, options = {}, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await apiCall(endpoint, options);
    } catch (error) {
      console.log(`Attempt ${attempt} failed:`, error.message);
      
      if (attempt === maxRetries) {
        throw new Error(`Failed after ${maxRetries} attempts: ${error.message}`);
      }
      
      // Wait before retry (exponential backoff)
      await new Promise(resolve => 
        setTimeout(resolve, Math.pow(2, attempt) * 1000)
      );
    }
  }
}

Loading States

javascript
class APIClient {
  constructor() {
    this.loadingStates = new Map();
  }

  setLoading(key, isLoading) {
    this.loadingStates.set(key, isLoading);
    console.log(`${key} loading:`, isLoading);
  }

  isLoading(key) {
    return this.loadingStates.get(key) || false;
  }

  async callWithLoading(key, apiFunction) {
    if (this.isLoading(key)) {
      console.log(`${key} is already loading`);
      return;
    }

    this.setLoading(key, true);
    try {
      const result = await apiFunction();
      return result;
    } finally {
      this.setLoading(key, false);
    }
  }
}

// Usage
const client = new APIClient();

async function loadUserData(userId) {
  return client.callWithLoading(`user-${userId}`, async () => {
    const user = await apiCall(`/users/${userId}`);
    return user;
  });
}

Tips and Best Practices

  1. Always handle errors - Network requests can fail
  2. Use async/await - More readable than Promise chains
  3. Implement caching - Reduce unnecessary API calls
  4. Add loading states - Better user experience
  5. Use AbortController - Cancel requests when needed
  6. Validate data - Check response structure before using
javascript
// Example with AbortController
async function fetchWithTimeout(endpoint, timeout = 5000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);
  
  try {
    const response = await fetch(`${BASE_URL}${endpoint}`, {
      signal: controller.signal
    });
    clearTimeout(timeoutId);
    return await response.json();
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Request timed out');
    }
    throw error;
  }
}

Fast Fake REST API powered by Bun + Elysia.js | Documentation site source: github.com/ckissi/jsonplaceholder