guard
保護異步函數,捕獲錯誤並返回統一的結果格式。
基礎用法
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)
}
語法
typescript
function guard<T>(
fn: () => Promise<T>
): Promise<{ data: T | null; error: Error | null }>
參數
fn
(function): 要保護的異步函數
返回值
返回一個Promise,解析為包含data和error的對象。
示例
基本錯誤處理
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)
處理網絡請求
typescript
import { guard } from 'radash'
async function makeApiCall(url: string) {
const result = await guard(async () => {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`)
}
return response.json()
})
return result
}
const apiResult = await makeApiCall('https://api.example.com/data')
if (apiResult.error) {
console.log('API Error:', apiResult.error.message)
} else {
console.log('API Data:', apiResult.data)
}
處理數據庫操作
typescript
import { guard } from 'radash'
async function createUser(userData: any) {
const result = await guard(async () => {
// 模擬數據庫操作
if (userData.email.includes('test')) {
throw new Error('Test emails are not allowed')
}
return {
id: Date.now(),
...userData,
createdAt: new Date()
}
})
if (result.error) {
console.error('User creation failed:', result.error.message)
return null
}
return result.data
}
const newUser = await createUser({
name: 'John Doe',
email: 'john@example.com'
})
處理文件操作
typescript
import { guard } from 'radash'
async function readFileContent(filePath: string) {
const result = await guard(async () => {
const fs = await import('fs/promises')
const content = await fs.readFile(filePath, 'utf-8')
return JSON.parse(content)
})
if (result.error) {
console.error('File read error:', result.error.message)
return null
}
return result.data
}
const config = await readFileContent('./config.json')
if (config) {
console.log('Config loaded:', config)
}
處理多個異步操作
typescript
import { guard } from 'radash'
async function processMultipleTasks() {
const tasks = [
guard(async () => {
await new Promise(resolve => setTimeout(resolve, 100))
return 'Task 1 completed'
}),
guard(async () => {
await new Promise(resolve => setTimeout(resolve, 200))
throw new Error('Task 2 failed')
}),
guard(async () => {
await new Promise(resolve => setTimeout(resolve, 150))
return 'Task 3 completed'
})
]
const results = await Promise.all(tasks)
results.forEach((result, index) => {
if (result.error) {
console.log(`Task ${index + 1} failed:`, result.error.message)
} else {
console.log(`Task ${index + 1} succeeded:`, result.data)
}
})
}
await processMultipleTasks()
處理超時操作
typescript
import { guard } from 'radash'
async function fetchWithTimeout(url: string, timeout: number) {
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)
throw error
}
})
return result
}
const data = await fetchWithTimeout('https://api.example.com/data', 5000)
if (data.error) {
console.log('Request failed:', data.error.message)
} else {
console.log('Data received:', data.data)
}
處理重試邏輯
typescript
import { guard } from 'radash'
async function fetchWithRetry(url: string, maxRetries: number = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const result = await guard(async () => {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
})
if (!result.error) {
return result.data
}
console.log(`Attempt ${attempt} failed:`, result.error.message)
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
}
}
throw new Error(`Failed after ${maxRetries} attempts`)
}
try {
const data = await fetchWithRetry('https://api.example.com/data')
console.log('Success:', data)
} catch (error) {
console.error('All attempts failed:', error.message)
}
處理並發操作
typescript
import { guard } from 'radash'
async function processConcurrentRequests(urls: string[]) {
const requests = urls.map(url =>
guard(async () => {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
})
)
const results = await Promise.all(requests)
const successful = results.filter(r => !r.error)
const failed = results.filter(r => r.error)
console.log(`Successful: ${successful.length}, Failed: ${failed.length}`)
return {
successful: successful.map(r => r.data),
failed: failed.map(r => r.error)
}
}
const urls = [
'https://api.example.com/users',
'https://api.example.com/posts',
'https://api.example.com/comments'
]
const { successful, failed } = await processConcurrentRequests(urls)
處理條件操作
typescript
import { guard } from 'radash'
async function conditionalOperation(shouldFail: boolean) {
const result = await guard(async () => {
if (shouldFail) {
throw new Error('Operation failed as requested')
}
// 模擬成功操作
await new Promise(resolve => setTimeout(resolve, 100))
return { success: true, timestamp: Date.now() }
})
return result
}
// 成功的情況
const successResult = await conditionalOperation(false)
if (successResult.data) {
console.log('Operation succeeded:', successResult.data)
}
// 失敗的情況
const failureResult = await conditionalOperation(true)
if (failureResult.error) {
console.log('Operation failed:', failureResult.error.message)
}
處理復雜錯誤處理
typescript
import { guard } from 'radash'
class CustomError extends Error {
constructor(message: string, public code: string) {
super(message)
this.name = 'CustomError'
}
}
async function complexOperation() {
const result = await guard(async () => {
// 模擬復雜的業務邏輯
const random = Math.random()
if (random < 0.3) {
throw new CustomError('Network error', 'NETWORK_ERROR')
} else if (random < 0.6) {
throw new CustomError('Validation error', 'VALIDATION_ERROR')
} else if (random < 0.8) {
throw new CustomError('Server error', 'SERVER_ERROR')
}
return { message: 'Operation completed successfully' }
})
if (result.error) {
if (result.error instanceof CustomError) {
switch (result.error.code) {
case 'NETWORK_ERROR':
console.log('Network issue, retrying...')
break
case 'VALIDATION_ERROR':
console.log('Invalid input data')
break
case 'SERVER_ERROR':
console.log('Server is down')
break
}
} else {
console.log('Unknown error:', result.error.message)
}
return null
}
return result.data
}
const result = await complexOperation()
注意事項
- 錯誤捕獲: 捕獲所有類型的錯誤,包括同步和異步錯誤
- 統一格式: 返回統一的結果格式,便於處理
- 類型安全: 提供完整的TypeScript類型支持
- 性能: 對性能影響很小,只是簡單的錯誤包裝
- 鏈式調用: 可以與其他異步函數鏈式調用
與其他方法的區別
try/catch
: 需要手動處理錯誤,guard
提供統一格式Promise.catch()
: 只處理Promise錯誤,guard
處理所有錯誤guard()
: radash提供的簡潔的錯誤處理工具
實際應用場景
- API調用: 處理網絡請求錯誤
- 數據庫操作: 處理數據庫連接和查詢錯誤
- 文件操作: 處理文件讀寫錯誤
- 第三方服務: 處理外部服務調用錯誤
- 業務邏輯: 保護復雜的業務操作