guard
Protect async functions, catch errors and return a unified result format.
Basic Usage
typescript
import { guard } from 'radash'
const result = await guard(async () => {
const response = await fetch('https://api.example.com/data')
return response.json()
})
if (result.error) {
console.log('Error:', result.error)
} else {
console.log('Data:', result.data)
}
Syntax
typescript
function guard<T>(
fn: () => Promise<T>
): Promise<{ data: T | null; error: Error | null }>
Parameters
fn
(function): The async function to protect
Return Value
Returns a Promise that resolves to an object containing data and error.
Examples
Basic Error Handling
typescript
import { guard } from 'radash'
async function fetchUserData(userId: number) {
const result = await guard(async () => {
const response = await fetch(`/api/users/${userId}`)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return response.json()
})
if (result.error) {
console.error('Failed to fetch user:', result.error.message)
return null
}
return result.data
}
const user = await fetchUserData(123)
Handle Network Requests
typescript
import { guard } from 'radash'
async function fetchMultipleUsers(userIds: number[]) {
const results = await Promise.all(
userIds.map(id =>
guard(async () => {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) {
throw new Error(`Failed to fetch user ${id}`)
}
return response.json()
})
)
)
return results.map(result =>
result.error ? { error: result.error.message } : { data: result.data }
)
}
const users = await fetchMultipleUsers([1, 2, 3, 4, 5])
Database Operations
typescript
import { guard } from 'radash'
async function createUser(userData: any) {
const result = await guard(async () => {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
})
if (!response.ok) {
throw new Error('Failed to create user')
}
return response.json()
})
if (result.error) {
console.error('User creation failed:', result.error.message)
return { success: false, error: result.error.message }
}
return { success: true, user: result.data }
}
File Operations
typescript
import { guard } from 'radash'
import { readFile, writeFile } from 'fs/promises'
async function processFile(filename: string) {
const readResult = await guard(async () => {
const content = await readFile(filename, 'utf8')
return JSON.parse(content)
})
if (readResult.error) {
console.error('Failed to read file:', readResult.error.message)
return null
}
const data = readResult.data
data.processed = true
data.timestamp = new Date().toISOString()
const writeResult = await guard(async () => {
await writeFile(filename, JSON.stringify(data, null, 2))
return data
})
if (writeResult.error) {
console.error('Failed to write file:', writeResult.error.message)
return null
}
return writeResult.data
}
API Rate Limiting
typescript
import { guard } from 'radash'
async function fetchWithRetry(url: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const result = await guard(async () => {
const response = await fetch(url)
if (response.status === 429) {
throw new Error('Rate limited')
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
})
if (!result.error) {
return result.data
}
if (result.error.message === 'Rate limited') {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
continue
}
throw result.error
}
throw new Error('Max retries exceeded')
}
Validation with Guard
typescript
import { guard } from 'radash'
async function validateAndProcess(data: any) {
const validationResult = await guard(async () => {
if (!data.email || !data.email.includes('@')) {
throw new Error('Invalid email')
}
if (!data.age || data.age < 0) {
throw new Error('Invalid age')
}
return data
})
if (validationResult.error) {
return { valid: false, error: validationResult.error.message }
}
const processResult = await guard(async () => {
// Process the validated data
const processed = { ...validationResult.data, processed: true }
return processed
})
if (processResult.error) {
return { valid: false, error: processResult.error.message }
}
return { valid: true, data: processResult.data }
}
Timeout Protection
typescript
import { guard } from 'radash'
async function fetchWithTimeout(url: string, timeout = 5000) {
const result = await guard(async () => {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)
try {
const response = await fetch(url, { signal: controller.signal })
clearTimeout(timeoutId)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
} catch (error) {
clearTimeout(timeoutId)
if (error.name === 'AbortError') {
throw new Error('Request timeout')
}
throw error
}
})
if (result.error) {
console.error('Request failed:', result.error.message)
return null
}
return result.data
}
Batch Processing
typescript
import { guard } from 'radash'
async function processBatch(items: any[]) {
const results = await Promise.all(
items.map(item =>
guard(async () => {
// Simulate processing
await new Promise(resolve => setTimeout(resolve, 100))
if (Math.random() < 0.1) {
throw new Error('Random processing error')
}
return { ...item, processed: true }
})
)
)
const successful = results.filter(r => !r.error).map(r => r.data)
const failed = results.filter(r => r.error).map(r => r.error)
return { successful, failed }
}
Notes
- Error handling: Automatically catches and wraps errors
- Type safety: Maintains TypeScript type safety
- Performance: Minimal overhead compared to try-catch
- Consistent format: Always returns { data, error } structure
- Async support: Designed specifically for async functions
Differences from Other Functions
guard
: Protects async functions with error handlingtry-catch
: Manual error handling, more verbosePromise.catch()
: Only handles Promise rejectionsguard()
: Provides structured error handling
Performance
- Time Complexity: O(1) overhead
- Memory: Minimal additional memory usage
- Use Cases: API calls, file operations, database queries