-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
162 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
type TaskExecutor<T> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void, onCancel: (callback: () => void) => void) => void; | ||
|
||
export class CancelableTask<T> { | ||
private promise: Promise<T>; | ||
private cancelCallback: (() => void) | null = null; | ||
private isCanceled = false; | ||
private cancelListeners: Array<() => void> = []; | ||
|
||
constructor(executor: TaskExecutor<T>) { | ||
this.promise = new Promise<T>((resolve, reject) => { | ||
const onCancel = (callback: () => void) => { | ||
this.cancelCallback = callback; | ||
}; | ||
|
||
executor( | ||
(value) => { | ||
if (!this.isCanceled) { | ||
resolve(value); | ||
} | ||
}, | ||
(reason) => { | ||
if (!this.isCanceled) { | ||
reject(reason); | ||
} | ||
}, | ||
onCancel | ||
); | ||
}); | ||
} | ||
|
||
public cancel() { | ||
if (this.cancelCallback) { | ||
this.cancelCallback(); | ||
} | ||
this.isCanceled = true; | ||
this.cancelListeners.forEach(listener => listener()); | ||
} | ||
|
||
public isTaskCanceled(): boolean { | ||
return this.isCanceled; | ||
} | ||
|
||
public onCancel(listener: () => void) { | ||
this.cancelListeners.push(listener); | ||
} | ||
|
||
public then<TResult1 = T, TResult2 = never>( | ||
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, | ||
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null | ||
): Promise<TResult1 | TResult2> { | ||
return this.promise.then(onfulfilled, onrejected); | ||
} | ||
|
||
public catch<TResult = never>( | ||
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null | ||
): Promise<T | TResult> { | ||
return this.promise.catch(onrejected); | ||
} | ||
|
||
public finally(onfinally?: (() => void) | undefined | null): Promise<T> { | ||
return this.promise.finally(onfinally); | ||
} | ||
|
||
[Symbol.asyncIterator]() { | ||
return { | ||
next: () => this.promise.then(value => ({ value, done: true })), | ||
}; | ||
} | ||
} | ||
|
||
|
||
async function demoAwait() { | ||
const executor: TaskExecutor<number> = (resolve, reject, onCancel) => { | ||
let count = 0; | ||
const intervalId = setInterval(() => { | ||
count++; | ||
console.log(`Task is running... Count: ${count}`); | ||
if (count === 5) { | ||
clearInterval(intervalId); | ||
resolve(count); | ||
} | ||
}, 1000); | ||
|
||
onCancel(() => { | ||
clearInterval(intervalId); | ||
console.log('Task has been canceled.'); | ||
reject(new Error('Task was canceled')); | ||
}); | ||
}; | ||
|
||
const task = new CancelableTask(executor); | ||
|
||
task.onCancel(() => { | ||
console.log('Cancel listener triggered.'); | ||
}); | ||
|
||
setTimeout(() => { | ||
task.cancel(); // 取消任务 | ||
}, 6000); | ||
|
||
try { | ||
const result = await task; | ||
console.log(`Task completed with result: ${result}`); | ||
} catch (error) { | ||
console.error('Task failed:', error); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
type Handler<T> = () => T | Promise<T>; | ||
|
||
export class Fallback<T> { | ||
private handlers: Handler<T>[] = []; | ||
|
||
add(handler: Handler<T>): this { | ||
this.handlers.push(handler); | ||
return this; | ||
} | ||
|
||
// 执行处理程序链 | ||
async run(): Promise<T> { | ||
const errors: Error[] = []; | ||
for (const handler of this.handlers) { | ||
try { | ||
const result = await handler(); | ||
if (result !== undefined) { | ||
return result; | ||
} | ||
} catch (error) { | ||
errors.push(error instanceof Error ? error : new Error(String(error))); | ||
} | ||
} | ||
throw new AggregateError(errors, 'All handlers failed'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters