tryit
安全地執行異步函數,返回 [error, result] 元組。
語法
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]>
參數
fn
(() => Promise<T> | (...args: Args) => Promise<T>): 要執行的異步函數...args
(Args, 可選): 傳遞給函數的參數
返回值
Promise<[Error | null, T | null]>
: 包含錯誤和結果的元組
示例
基本用法
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)
}
處理網絡請求
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)
處理文件操作
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)
// 使用默認配置
return defaultConfig
}
const config = JSON.parse(content)
console.log('Config loaded:', config)
處理數據庫操作
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: 'Alice',
email: 'alice@example.com'
})
if (err) {
console.error('Failed to create user:', err)
return { success: false, error: err.message }
}
return { success: true, userId: result.insertId }
處理多個操作
typescript
import { tryit } from 'radash'
const operations = [
() => fetch('/api/users'),
() => fetch('/api/posts'),
() => fetch('/api/comments')
]
const results = await Promise.all(
operations.map(op => tryit(op))
)
const errors = results.filter(([err]) => err)
const successes = results.filter(([, data]) => data)
console.log('Errors:', errors.length)
console.log('Successes:', successes.length)
處理超時
typescript
import { tryit } from 'radash'
const timeout = (ms: number) =>
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
)
const slowOperation = async () => {
await new Promise(resolve => setTimeout(resolve, 2000))
return 'Operation completed'
}
const [err, result] = await tryit(async () => {
return await Promise.race([
slowOperation(),
timeout(1000)
])
})
if (err) {
console.error('Operation timed out:', err)
} else {
console.log('Result:', result)
}
處理驗證
typescript
import { tryit } from 'radash'
const validateUser = async (userData: any) => {
if (!userData.email) {
throw new Error('Email is required')
}
if (!userData.email.includes('@')) {
throw new Error('Invalid email format')
}
return userData
}
const [err, validatedUser] = await tryit(validateUser, {
name: 'Alice',
email: 'invalid-email'
})
if (err) {
console.error('Validation failed:', err.message)
return { success: false, error: err.message }
}
console.log('User validated:', validatedUser)
處理第三方API
typescript
import { tryit } from 'radash'
const callExternalAPI = async (endpoint: string) => {
const response = await fetch(`https://api.external.com/${endpoint}`)
if (!response.ok) {
throw new Error(`API error: ${response.status}`)
}
return response.json()
}
const [err, data] = await tryit(callExternalAPI, 'users/123')
if (err) {
console.error('External API error:', err)
// 使用緩存數據或默認值
return cachedData
}
console.log('External API data:', data)
處理文件上傳
typescript
import { tryit } from 'radash'
const uploadFile = async (file: File) => {
const formData = new FormData()
formData.append('file', file)
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
})
if (!response.ok) {
throw new Error(`Upload failed: ${response.status}`)
}
return response.json()
}
const [err, uploadResult] = await tryit(uploadFile, fileInput.files[0])
if (err) {
console.error('Upload failed:', err)
showErrorMessage('文件上傳失敗')
} else {
console.log('Upload successful:', uploadResult)
showSuccessMessage('文件上傳成功')
}
處理並發操作
typescript
import { tryit } from 'radash'
const fetchWithRetry = async (url: string, retries = 3) => {
for (let i = 0; i < retries; i++) {
const [err, data] = await tryit(fetch)(url)
if (!err) {
return data
}
if (i < retries - 1) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)))
}
}
throw new Error(`Failed after ${retries} retries`)
}
const [err, data] = await tryit(fetchWithRetry)('/api/unreliable-endpoint')
if (err) {
console.error('All retries failed:', err)
} else {
console.log('Data received:', data)
}
注意事項
- 錯誤處理: 總是檢查第一個元素是否為錯誤
- 類型安全: 支持完整的 TypeScript 類型推斷
- 性能: 比 try-catch 更簡潔,但功能相同
- 可讀性: 使錯誤處理更加明確和一致
與其他函數的區別
tryit
: 返回 [error, result] 元組try-catch
: 原生錯誤處理guard
: 類似功能,但可能有不同的實現
性能
- 時間復雜度: O(1)
- 內存使用: 與原生 try-catch 相同
- 適用場景: 需要統一錯誤處理的異步操作