LazyMan
本文寫于 2020 年 12 月 22 日
看到一個非常有意思的題目,叫做 LazyMan:
實作一個 LazyMan,可以按照以下方式呼叫:LazyMan("Hank");,輸出:Hi! This is Hank!,
要求:
LazyMan('Hank').sleep(10).eat('dinner');
// Hi! This is Hank!
// 等待10秒..
// Wake up after 10
// Eat dinner~
LazyMan('Hank').eat('dinner').eat('supper');
// Hi This is Hank!
// Eat dinner~
// Eat supper~
LazyMan('Hank').sleepFirst(5).eat('supper');
// 等待5秒
// Wake up after 5
// Hi This is Hank!
// Eat supper~
經過初步的分析,這道題的考點應該有兩點:
- 鏈式呼叫
- 任務佇列
如何實作鏈式呼叫?
在 jQuery 的設計中就存在大量的鏈式呼叫:$('#app').addClass('xxx').xxxx(),
如果 $ 函式長這樣:
function $(selector: string) {
const doms = document.querySelectorAll(selector);
return {
doms,
addClass: () => {
// ...
},
xxxx: () => {
// ...
},
};
}
這樣子我們是沒辦法使用鏈式呼叫的,
因為在呼叫完了 addClass 函式之后回傳的是 undefined,我們無法在 undefined 上呼叫 xxxx,
所以我們需要回傳一個 Api 物件,
function $() {
const api = {
doms,
addClass: () => {
// ,,,
return api;
},
xxxx: () => {
// ...
return api;
},
};
return api;
}
所以很顯然,我們的 LazyMan 函式應該長這樣:
const LazyMan = () => {
const eat = () => {
console.log('我吃飯了');
return api;
};
const sleep = () => {
console.log('我睡覺了');
return api;
};
const sleepFirst = () => {
console.log('我先睡了');
return api;
};
const api = {
eat,
sleep,
sleepFirst,
};
};
任務佇列
分析題目,我們發現 sleep 函式很好實作,但 sleepFirst 并不方便——我們不可能讓之后執行的函式超越時間的阻隔,跑到最前面執行——這是違背規律的,
所以我們必然需要創建一個佇列,
const LazyMan = () => {
const queue = [];
// ...
};
該佇列存放的就是每次的任務函式,呼叫一般的 api 時,往隊伍末尾加上任務即可,而 sleepFirst 做的只是把任務“插隊”,放到佇列開頭,
所以我們的順序就是:執行 LazyMan => 呼叫 api 時將函式加入佇列 => 如果是 First 就需要插隊 => 任務呼叫結束后執行佇列下一項 => 開始 => 執行佇列第一項,
const LazyMan = (name: string) => {
const queue: any[] = [];
queue.push(() => {
console.log(`你好,${name}`);
next();
});
const next = () => {
const task = queue.shift();
task?.();
};
const eat = () => {
const action = () => {
console.log(`${name} 吃飯了`);
next();
};
queue.push(action);
return api;
};
const sleep = (n: number) => {
const action = () => {
setTimeout(() => {
console.log(`睡了 ${n} 秒,我睡醒了`);
next();
}, n * 1000);
};
queue.push(action);
return api;
};
const sleepFirst = (n: number) => {
const action = () => {
setTimeout(() => {
console.log(`睡了 ${n} 秒,我睡醒了`);
next();
}, n * 1000);
};
queue.unshift(action);
return api;
};
const api = {
eat,
sleep,
sleepFirst,
};
setTimeout(() => next(), 0);
return api;
};
LazyMan('Han').sleep(3).eat();
(完)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/241808.html
標籤:其他
上一篇:react-antd JYadmin 封裝的優秀后臺模板集成方案("^1.0.0") -- 第2節:【react+antd layout-路由模塊】
下一篇:去哪里了?幾部關于IT的劇推薦
