實現(xiàn)一個方法的鏈式調(diào)用
作者:一川
這個需求是一個典型的異步鏈式調(diào)用場景,尤其是?sleep?延遲后再繼續(xù)執(zhí)行后續(xù)操作。實現(xiàn)時關(guān)鍵在于:每次調(diào)用都注冊一個異步任務(wù);按順序排隊執(zhí)行(使用?Promise?鏈或任務(wù)隊列);每個方法返回?this?以保持鏈式調(diào)用。
題目描述
請使用 TypeScript 實現(xiàn)一個支持鏈式調(diào)用的 Cat 類,要求如下:
cat.say("Tom")
:立即輸出hello Tom
到控制臺;cat.sleep(3000)
:等待 3000 毫秒后再繼續(xù)執(zhí)行后續(xù)任務(wù);cat.bye("Bye")
:輸出 Bye 到控制臺。
調(diào)用示例:
const cat = new Cat();
cat.say("Tom").sleep(3000).bye("Bye");
期望輸出:
hello Tom
# 等待 3 秒...
Bye
題目解析
這個需求是一個典型的 異步鏈式調(diào)用 場景,尤其是 sleep
延遲后再繼續(xù)執(zhí)行后續(xù)操作。實現(xiàn)時關(guān)鍵在于:
- 每次調(diào)用都注冊一個異步任務(wù);
- 按順序排隊執(zhí)行(使用
Promise
鏈或任務(wù)隊列); - 每個方法返回
this
以保持鏈式調(diào)用。
代碼實現(xiàn)
class Cat {
private taskQueue: (() => Promise<void>)[] = [];
constructor() {
// 自動開始執(zhí)行任務(wù)隊列
Promise.resolve().then(() => this.runQueue());
}
private async runQueue() {
for (const task of this.taskQueue) {
await task();
}
}
say(name: string): this {
this.taskQueue.push(() => {
return new Promise<void>((resolve) => {
console.log("hello", name);
resolve();
});
});
return this;
}
sleep(ms: number): this {
this.taskQueue.push(() => {
return new Promise<void>((resolve) => {
setTimeout(resolve, ms);
});
});
return this;
}
bye(msg: string): this {
this.taskQueue.push(() => {
return new Promise<void>((resolve) => {
console.log(msg);
resolve();
});
});
return this;
}
}
// 使用方式
const cat = new Cat();
cat.say("Tom").sleep(3000).bye("Bye");
說明:
- taskQueue 是一個異步任務(wù)列表。
- 每個方法通過 this.taskQueue.push(() => Promise) 添加一個任務(wù)。
- 構(gòu)造函數(shù)中立即開始異步執(zhí)行任務(wù)隊列。
- sleep 實現(xiàn)延遲,后續(xù)任務(wù)自然排隊執(zhí)行。
拓展
如果要進行逆向鏈式調(diào)用,如何實現(xiàn)呢?
cat.bye("Bye").sleep(2000).say("Say");
執(zhí)行順序:
Say
# 等待 2 秒...
Bye
所有方法仍然鏈式調(diào)用,但執(zhí)行順序以調(diào)用順序為準,同時 sleep 是延遲“下一個任務(wù)”的執(zhí)行,而不是“當前任務(wù)”的延遲。
class Cat {
private queue: { fn: () => void; delay: number }[] = [];
private nextDelay = 0;
constructor() {
Promise.resolve().then(() => this.run());
}
private async run() {
for (const task of this.queue) {
if (task.delay > 0) {
await new Promise((res) => setTimeout(res, task.delay));
}
task.fn();
}
}
private addTask(fn: () => void): this {
this.queue.push({ fn, delay: this.nextDelay });
this.nextDelay = 0; // reset after applying
return this;
}
say(msg: string): this {
return this.addTask(() => {
console.log(msg);
});
}
bye(msg: string): this {
return this.addTask(() => {
console.log(msg);
});
}
sleep(ms: number): this {
this.nextDelay = ms; // apply to next task
return this;
}
}
責任編輯:武曉燕
來源:
宇宙一馬平川