Open 981377660LMT opened 1 month ago
type AsyncFunction<T extends any[], R> = (...args: T) => Promise<R>
interface LockifyOptions {
failureStrategy: 'block' | 'ignore'
}
function lockify<T extends any[], R>(fn: AsyncFunction<T, R>, options: LockifyOptions): AsyncFunction<T, R | void> {
let locked = false
const queue: Array<{ resolve: (value: R | void) => void; reject: (reason?: any) => void; args: T }> = []
return async (...args: T): Promise<R | void> => {
if (!locked) {
return run(...args)
}
switch (options.failureStrategy) {
case 'block':
return new Promise((resolve, reject) => {
queue.push({ resolve, reject, args })
})
case 'ignore':
return
}
}
async function run(...args: T): Promise<R> {
locked = true
try {
return await fn(...args)
} finally {
locked = false
processQueue()
}
}
function processQueue(): void {
if (!queue.length) return
const { resolve, reject, args } = queue.shift()!
run(...args)
.then(resolve)
.catch(reject)
}
}
export {}
if (require.main === module) {
// 使用示例
async function fetchData(): Promise<string> {
await new Promise(resolve => setTimeout(resolve, 2000))
return '请求结果'
}
const blockingFetch = lockify(fetchData, { failureStrategy: 'block' })
console.log('测试阻塞行为')
blockingFetch().then(console.log)
blockingFetch().then(console.log)
blockingFetch().then(console.log)
const ignoringFetch = lockify(fetchData, { failureStrategy: 'ignore' })
console.log('测试忽略行为')
ignoringFetch().then(console.log)
ignoringFetch().then(console.log)
ignoringFetch().then(console.log)
}
获取锁失败时的策略主要取决于应用场景和需求,但通常可以归纳为以下几种:
阻塞(Blocking):
忽略(Ignoring):
超时(Timeout):
重试(Retrying):
回调(Callback):
优先级(Prioritization):
条件执行(Conditional Execution):
每种策略都有其适用场景和潜在的权衡。选择哪种策略应基于对性能、资源利用、用户体验和业务逻辑的综合考虑。在实际应用中,可能会根据具体需求组合使用多种策略。