/**
* Fetches user data from the API by user ID
* @param {number} id - The user ID to fetch
* @returns {Promise<Object|null>} User data object or null if invalid/not found
* @throws {Error} When the API request fails
*/
async function getUserData(id) {
// Early validation
if (!id || id <= 0) {
return null;
}
try {
const response = await fetch(`https://api.example.com/users/${id}`);
// Check if response is successful
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const userData = await response.json();
// Validate user data structure
return isValidUserData(userData) ? userData : null;
} catch (error) {
console.error(`Failed to fetch user data for ID ${id}:`, error.message);
throw error; // Re-throw to allow caller to handle
}
}
/**
* Validates user data structure
* @param {Object} userData - User data object to validate
* @returns {boolean} True if valid, false otherwise
*/
function isValidUserData(userData) {
return (
userData &&
typeof userData === 'object' &&
typeof userData.email === 'string' &&
userData.email.includes('@')
);
}
// Alternative version with custom error types for better error handling
class UserDataError extends Error {
constructor(message, code) {
super(message);
this.name = 'UserDataError';
this.code = code;
}
}
async function getUserDataWithCustomErrors(id) {
if (!id || id <= 0) {
throw new UserDataError('Invalid user ID provided', 'INVALID_ID');
}
try {
const response = await fetch(`https://api.example.com/users/${id}`);
if (!response.ok) {
throw new UserDataError(
`API request failed with status ${response.status}`,
'API_ERROR'
);
}
const userData = await response.json();
if (!isValidUserData(userData)) {
throw new UserDataError('Invalid user data structure', 'INVALID_DATA');
}
return userData;
} catch (error) {
if (error instanceof UserDataError) {
throw error;
}
// Network or parsing errors
throw new UserDataError(
`Failed to fetch user data: ${error.message}`,
'NETWORK_ERROR'
);
}
}