proxied
创建一个代理函数,可以拦截和修改函数的调用、参数和返回值。
基础用法
typescript
import { proxied } from 'radash'
const add = (a: number, b: number) => a + b
const proxiedAdd = proxied(add, {
before: (args) => console.log('Before call:', args),
after: (result) => console.log('After call:', result)
})
console.log(proxiedAdd(2, 3)) // Before call: [2, 3] After call: 5 5
语法
typescript
function proxied<T extends any[], R>(
fn: (...args: T) => R,
handlers: {
before?: (args: T) => void | T,
after?: (result: R) => void | R,
error?: (error: any) => void | R
}
): (...args: T) => R
参数
fn
(function): 要代理的函数handlers
(object): 代理处理器对象before
(function): 调用前的处理器after
(function): 调用后的处理器error
(function): 错误处理器
返回值
返回一个代理函数,具有与原函数相同的签名。
示例
基本日志记录
typescript
import { proxied } from 'radash'
const multiply = (a: number, b: number) => a * b
const loggedMultiply = proxied(multiply, {
before: (args) => console.log(`Calling multiply with args: ${args}`),
after: (result) => console.log(`Multiply returned: ${result}`)
})
console.log(loggedMultiply(4, 5)) // Calling multiply with args: 4,5 Multiply returned: 20 20
参数验证
typescript
import { proxied } from 'radash'
const divide = (a: number, b: number) => a / b
const safeDivide = proxied(divide, {
before: (args) => {
const [a, b] = args
if (b === 0) {
throw new Error('Division by zero')
}
if (typeof a !== 'number' || typeof b !== 'number') {
throw new Error('Arguments must be numbers')
}
return args
},
error: (error) => {
console.error('Division error:', error.message)
return 0
}
})
console.log(safeDivide(10, 2)) // 5
console.log(safeDivide(10, 0)) // Division error: Division by zero 0
性能监控
typescript
import { proxied } from 'radash'
const expensiveOperation = (n: number) => {
let result = 0
for (let i = 0; i < n; i++) {
result += i
}
return result
}
const monitoredOperation = proxied(expensiveOperation, {
before: (args) => {
console.time(`Operation with ${args[0]}`)
return args
},
after: (result) => {
console.timeEnd(`Operation with ${result}`)
return result
}
})
console.log(monitoredOperation(1000000)) // Operation with 1000000: 15.234ms 499999500000
缓存机制
typescript
import { proxied } from 'radash'
const cache = new Map()
const fetchUser = async (id: number) => {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 100))
return { id, name: `User ${id}`, email: `user${id}@example.com` }
}
const cachedFetchUser = proxied(fetchUser, {
before: async (args) => {
const [id] = args
const cacheKey = `user_${id}`
if (cache.has(cacheKey)) {
console.log(`Cache hit for user ${id}`)
return [cache.get(cacheKey)]
}
console.log(`Cache miss for user ${id}`)
return args
},
after: async (result) => {
const cacheKey = `user_${result.id}`
cache.set(cacheKey, result)
return result
}
})
// 第一次调用
await cachedFetchUser(1) // Cache miss for user 1
// 第二次调用
await cachedFetchUser(1) // Cache hit for user 1
重试机制
typescript
import { proxied } from 'radash'
const unreliableApi = async (id: number) => {
if (Math.random() < 0.7) {
throw new Error('API Error')
}
return { id, data: `Data for ${id}` }
}
const retryCount = new Map()
const retryApi = proxied(unreliableApi, {
before: (args) => {
const [id] = args
retryCount.set(id, (retryCount.get(id) || 0) + 1)
return args
},
error: async (error) => {
const currentRetries = Math.max(...retryCount.values())
if (currentRetries < 3) {
console.log(`Retrying... (attempt ${currentRetries})`)
await new Promise(resolve => setTimeout(resolve, 1000))
return await unreliableApi(...Array.from(retryCount.keys())[0])
}
console.error('Max retries reached')
return { error: 'Max retries reached' }
}
})
await retryApi(1)
参数转换
typescript
import { proxied } from 'radash'
const processData = (data: any[]) => {
return data.map(item => item * 2)
}
const validatedProcessData = proxied(processData, {
before: (args) => {
const [data] = args
if (!Array.isArray(data)) {
throw new Error('Input must be an array')
}
// 过滤非数字值
const filteredData = data.filter(item => typeof item === 'number')
console.log(`Filtered ${data.length - filteredData.length} non-numeric items`)
return [filteredData]
},
after: (result) => {
console.log(`Processed ${result.length} items`)
return result
}
})
console.log(validatedProcessData([1, 2, 'a', 3, 'b', 4])) // Filtered 2 non-numeric items Processed 4 items [2, 4, 6, 8]
结果转换
typescript
import { proxied } from 'radash'
const getUserInfo = (id: number) => {
return { id, name: `User ${id}`, email: `user${id}@example.com` }
}
const sanitizedGetUserInfo = proxied(getUserInfo, {
after: (result) => {
// 移除敏感信息
const { email, ...sanitized } = result
return sanitized
}
})
console.log(sanitizedGetUserInfo(1)) // { id: 1, name: 'User 1' }
异步错误处理
typescript
import { proxied } from 'radash'
const asyncOperation = async (data: any) => {
if (data.error) {
throw new Error('Simulated error')
}
return { success: true, data }
}
const robustAsyncOperation = proxied(asyncOperation, {
error: async (error) => {
console.error('Operation failed:', error.message)
return { success: false, error: error.message, fallback: 'default' }
}
})
// 成功情况
console.log(await robustAsyncOperation({ id: 1 })) // { success: true, data: { id: 1 } }
// 失败情况
console.log(await robustAsyncOperation({ error: true })) // Operation failed: Simulated error { success: false, error: 'Simulated error', fallback: 'default' }
权限检查
typescript
import { proxied } from 'radash'
const userPermissions = {
admin: ['read', 'write', 'delete'],
user: ['read'],
guest: []
}
const checkPermission = (user: string, action: string) => {
const permissions = userPermissions[user as keyof typeof userPermissions] || []
return permissions.includes(action)
}
const secureOperation = (user: string, action: string, data: any) => {
return { user, action, data, timestamp: new Date() }
}
const securedOperation = proxied(secureOperation, {
before: (args) => {
const [user, action] = args
if (!checkPermission(user, action)) {
throw new Error(`User ${user} does not have permission to ${action}`)
}
console.log(`User ${user} performing ${action}`)
return args
},
error: (error) => {
console.error('Permission denied:', error.message)
return { error: error.message, timestamp: new Date() }
}
})
console.log(securedOperation('admin', 'write', { content: 'test' })) // User admin performing write { user: 'admin', action: 'write', data: { content: 'test' }, timestamp: ... }
console.log(securedOperation('guest', 'write', { content: 'test' })) // Permission denied: User guest does not have permission to write { error: 'User guest does not have permission to write', timestamp: ... }
数据验证
typescript
import { proxied } from 'radash'
const createUser = (name: string, email: string, age: number) => {
return { id: Math.random().toString(36), name, email, age }
}
const validatedCreateUser = proxied(createUser, {
before: (args) => {
const [name, email, age] = args
const errors: string[] = []
if (!name || name.length < 2) {
errors.push('Name must be at least 2 characters')
}
if (!email || !email.includes('@')) {
errors.push('Email must be valid')
}
if (age < 0 || age > 150) {
errors.push('Age must be between 0 and 150')
}
if (errors.length > 0) {
throw new Error(errors.join(', '))
}
return args
},
error: (error) => {
console.error('Validation failed:', error.message)
return { error: error.message, valid: false }
}
})
console.log(validatedCreateUser('Alice', 'alice@example.com', 25)) // { id: 'abc123', name: 'Alice', email: 'alice@example.com', age: 25 }
console.log(validatedCreateUser('A', 'invalid-email', 200)) // Validation failed: Name must be at least 2 characters, Email must be valid, Age must be between 0 and 150 { error: 'Name must be at least 2 characters, Email must be valid, Age must be between 0 and 150', valid: false }
性能优化
typescript
import { proxied } from 'radash'
const heavyComputation = (n: number) => {
let result = 0
for (let i = 0; i < n; i++) {
result += Math.sqrt(i)
}
return result
}
const optimizedComputation = proxied(heavyComputation, {
before: (args) => {
const [n] = args
if (n > 1000000) {
console.warn('Large computation detected, consider optimization')
}
return args
},
after: (result) => {
if (result > 1000000) {
console.log('Large result generated')
}
return result
}
})
console.log(optimizedComputation(100000)) // Large computation detected, consider optimization Large result generated 666666.6666666666
调试工具
typescript
import { proxied } from 'radash'
const complexFunction = (a: number, b: string, c: boolean) => {
return { sum: a + parseInt(b), flag: c }
}
const debugFunction = proxied(complexFunction, {
before: (args) => {
console.group('Function Call')
console.log('Arguments:', args)
console.log('Argument types:', args.map(arg => typeof arg))
console.groupEnd()
return args
},
after: (result) => {
console.group('Function Result')
console.log('Return value:', result)
console.log('Return type:', typeof result)
console.groupEnd()
return result
}
})
console.log(debugFunction(5, '10', true))
// Function Call
// Arguments: [5, '10', true]
// Argument types: ['number', 'string', 'boolean']
// Function Result
// Return value: { sum: 15, flag: true }
// Return type: object
// { sum: 15, flag: true }
链式代理
typescript
import { proxied } from 'radash'
const baseFunction = (x: number) => x * 2
const loggedFunction = proxied(baseFunction, {
before: (args) => {
console.log('Before:', args)
return args
},
after: (result) => {
console.log('After:', result)
return result
}
})
const validatedFunction = proxied(loggedFunction, {
before: (args) => {
const [x] = args
if (x < 0) {
throw new Error('Negative numbers not allowed')
}
return args
},
error: (error) => {
console.error('Error:', error.message)
return 0
}
})
console.log(validatedFunction(5)) // Before: [5] After: 10 10
console.log(validatedFunction(-5)) // Error: Negative numbers not allowed 0
注意事项
- 处理器返回值:
before
处理器可以返回修改后的参数数组 - 错误处理:
error
处理器可以返回替代值或重新抛出错误 - 异步支持: 支持异步函数和异步处理器
- 性能影响: 代理会带来轻微的性能开销
- 类型安全: 支持TypeScript类型推断
与其他方法的区别
proxied()
: 创建函数代理,支持拦截和修改curry()
: 柯里化函数debounce()
: 防抖函数throttle()
: 节流函数
实际应用场景
- 日志记录: 记录函数调用和返回值
- 性能监控: 测量函数执行时间
- 缓存机制: 缓存函数结果
- 错误处理: 统一处理函数错误
- 参数验证: 验证函数参数
- 权限检查: 检查函数调用权限
- 调试工具: 调试函数执行过程