tryit
Safely execute async functions, returning [error, result] tuples.
Syntax
typescript
tryit<T>(
fn: () => Promise<T>
): Promise<[Error | null, T | null]>
tryit<T, Args extends any[]>(
fn: (...args: Args) => Promise<T>,
...args: Args
): Promise<[Error | null, T | null]>
Parameters
fn
(() => Promise<T> | (...args: Args) => Promise<T>): The async function to execute...args
(Args, optional): Arguments to pass to the function
Return Value
Promise<[Error | null, T | null]>
: Tuple containing error and result
Examples
Basic Usage
typescript
import { tryit } from 'radash'
const fetchUser = async (id: number) => {
const response = await fetch(`/api/users/${id}`)
return response.json()
}
const [err, user] = await tryit(fetchUser, 123)
if (err) {
console.error('Failed to fetch user:', err)
} else {
console.log('User:', user)
}
Handle Network Requests
typescript
import { tryit } from 'radash'
const [err, data] = await tryit(fetch)('/api/users')
if (err) {
console.error('Network error:', err)
return
}
const users = await data.json()
console.log('Users:', users)
Handle File Operations
typescript
import { tryit } from 'radash'
import { readFile } from 'fs/promises'
const [err, content] = await tryit(readFile)('config.json', 'utf8')
if (err) {
console.error('Failed to read file:', err)
// Use default config
return defaultConfig
}
const config = JSON.parse(content)
console.log('Config loaded:', config)
Handle Database Operations
typescript
import { tryit } from 'radash'
const createUser = async (userData: any) => {
return await db.query(
'INSERT INTO users (name, email) VALUES (?, ?)',
[userData.name, userData.email]
)
}
const [err, result] = await tryit(createUser, {
name: 'John Doe',
email: 'john@example.com'
})
if (err) {
console.error('Failed to create user:', err)
return
}
console.log('User created:', result)
Handle Multiple Operations
typescript
import { tryit } from 'radash'
async function processUserData(userId: number) {
// Fetch user data
const [userErr, user] = await tryit(async () => {
const response = await fetch(`/api/users/${userId}`)
return response.json()
})
if (userErr) {
console.error('Failed to fetch user:', userErr)
return null
}
// Fetch user posts
const [postsErr, posts] = await tryit(async () => {
const response = await fetch(`/api/users/${userId}/posts`)
return response.json()
})
if (postsErr) {
console.error('Failed to fetch posts:', postsErr)
return { user, posts: [] }
}
return { user, posts }
}
const result = await processUserData(123)
console.log('User data:', result)
Handle Validation
typescript
import { tryit } from 'radash'
const validateUser = async (userData: any) => {
if (!userData.email || !userData.email.includes('@')) {
throw new Error('Invalid email')
}
if (!userData.age || userData.age < 0) {
throw new Error('Invalid age')
}
return userData
}
const [err, validatedUser] = await tryit(validateUser, {
name: 'Alice',
email: 'alice@example.com',
age: 25
})
if (err) {
console.error('Validation failed:', err.message)
return
}
console.log('User validated:', validatedUser)
Handle Timeout Operations
typescript
import { tryit } from 'radash'
const fetchWithTimeout = async (url: string, timeout: number) => {
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)
throw error
}
}
const [err, data] = await tryit(fetchWithTimeout)('https://api.example.com/data', 5000)
if (err) {
console.error('Request failed:', err.message)
return
}
console.log('Data received:', data)
Handle Batch Operations
typescript
import { tryit } from 'radash'
async function processBatch(items: any[]) {
const results = []
for (const item of items) {
const [err, result] = await tryit(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 }
})
if (err) {
console.error(`Failed to process item:`, err.message)
results.push({ ...item, error: err.message })
} else {
results.push(result)
}
}
return results
}
const items = [{ id: 1 }, { id: 2 }, { id: 3 }]
const processed = await processBatch(items)
console.log('Processed items:', processed)
Handle Conditional Operations
typescript
import { tryit } from 'radash'
const processWithCondition = async (data: any, shouldProcess: boolean) => {
if (!shouldProcess) {
throw new Error('Processing not allowed')
}
// Simulate processing
await new Promise(resolve => setTimeout(resolve, 1000))
return { ...data, processed: true }
}
const [err, result] = await tryit(processWithCondition)({ id: 1, name: 'test' }, true)
if (err) {
console.error('Processing failed:', err.message)
return
}
console.log('Processing successful:', result)
Handle Complex Error Handling
typescript
import { tryit } from 'radash'
class CustomError extends Error {
constructor(message: string, public code: string) {
super(message)
this.name = 'CustomError'
}
}
const complexOperation = async (input: any) => {
if (!input.id) {
throw new CustomError('Missing ID', 'VALIDATION_ERROR')
}
if (input.id < 0) {
throw new CustomError('Invalid ID', 'INVALID_INPUT')
}
// Simulate async work
await new Promise(resolve => setTimeout(resolve, 500))
return { ...input, processed: true }
}
const [err, result] = await tryit(complexOperation)({ id: 123, name: 'test' })
if (err) {
if (err instanceof CustomError) {
switch (err.code) {
case 'VALIDATION_ERROR':
console.error('Validation error:', err.message)
break
case 'INVALID_INPUT':
console.error('Invalid input:', err.message)
break
default:
console.error('Unknown error:', err.message)
}
} else {
console.error('Unexpected error:', err.message)
}
return
}
console.log('Operation successful:', result)
Handle API Rate Limiting
typescript
import { tryit } from 'radash'
const fetchWithRateLimit = async (url: string) => {
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()
}
const [err, data] = await tryit(fetchWithRateLimit)('https://api.example.com/data')
if (err) {
if (err.message === 'Rate limited') {
console.log('Rate limited, will retry later')
// Implement retry logic
} else {
console.error('Request failed:', err.message)
}
return
}
console.log('Data received:', data)
Handle File System Operations
typescript
import { tryit } from 'radash'
import { readFile, writeFile, unlink } from 'fs/promises'
async function processFile(inputPath: string, outputPath: string) {
// Read file
const [readErr, content] = await tryit(readFile)(inputPath, 'utf8')
if (readErr) {
console.error('Failed to read file:', readErr.message)
return
}
// Process content
const processed = content.toUpperCase()
// Write processed file
const [writeErr] = await tryit(writeFile)(outputPath, processed)
if (writeErr) {
console.error('Failed to write file:', writeErr.message)
return
}
// Clean up original file
const [deleteErr] = await tryit(unlink)(inputPath)
if (deleteErr) {
console.error('Failed to delete original file:', deleteErr.message)
}
return { inputPath, outputPath, size: processed.length }
}
const result = await processFile('./input.txt', './output.txt')
console.log('File processed:', result)
Handle Database Transactions
typescript
import { tryit } from 'radash'
const executeTransaction = async (operations: any[]) => {
// Start transaction
await db.beginTransaction()
try {
const results = []
for (const operation of operations) {
const [err, result] = await tryit(async () => {
return await db.query(operation.query, operation.params)
})
if (err) {
throw err
}
results.push(result)
}
// Commit transaction
await db.commit()
return results
} catch (error) {
// Rollback transaction
await db.rollback()
throw error
}
}
const operations = [
{ query: 'INSERT INTO users (name) VALUES (?)', params: ['Alice'] },
{ query: 'INSERT INTO users (name) VALUES (?)', params: ['Bob'] }
]
const [err, results] = await tryit(executeTransaction)(operations)
if (err) {
console.error('Transaction failed:', err.message)
return
}
console.log('Transaction successful:', results)
Notes
- Error handling: Returns errors instead of throwing them
- Type safety: Provides full TypeScript support
- Performance: Minimal overhead compared to try-catch
- Consistent format: Always returns [error, result] tuple
- Async support: Designed specifically for async functions
Differences from Other Functions
tryit
: Returns error and result tupleguard
: Returns object with error and data propertiestry-catch
: Throws errors instead of returning themtryit()
: More functional approach to error handling
Performance
- Time Complexity: O(1) overhead
- Memory: Minimal additional memory usage
- Use Cases: API calls, file operations, database queries