源碼地址:github.com/flitrue/ts-…前端
先看題目:ios
function sleep(timeout: number): Promise {
// 待實現
}
複製代碼
下面咱們開始分析這道面試題:git
sleep函數是能夠暫停函數在一段時間內執行,在沒有promise的時代,sleep函數基本都是經過setTimeout控制的,promise出現之後,貌似前端coder發現了新大陸,各類花裏胡哨的擼它,創造出各類各樣的異步編程庫,好比目前最流行的axios。github
首先咱們不考慮ts實現,下面是我初版的實現:面試
function sleep(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout))
}
複製代碼
看着很簡單又簡潔,經過返回一個Promise實例,到了指定的時間執行resolve方法。可是這種實現只知足了面試題中的第一個問題。接下來咱們須要考慮如何中斷promise,實現提早結束讓程序繼續執行。typescript
也許喜歡專研的同窗,看到這裏確定會想到axios庫中有個CancelToken
,能夠取消請求。CancelToken
基本使用以下:編程
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
複製代碼
下面是個人改進,在promise增長一個cancel屬性,返回resolve方法axios
function sleep(timeout) {
var res;
var promise = new Promise(function (resolve) {
res = resolve;
setTimeout(function () {
resolve('done');
}, timeout);
});
promise.cancel = res;
return promise;
}
複製代碼
第一個和第二個問題解決了,咱們寫幾個測試用例,驗證咱們的函數正確性。promise
// 測試用例1
function test1() {
console.info('test1 start');
sleep(2000).then(function (res) {
console.log('2s later ' + res);
});
}
test1(); // result: 2s later done
複製代碼
// 測試用例2
function test2() {
console.info('test2 start');
var p = sleep(5000);
p.then(function (res) {
console.log(res);
});
setTimeout(function () {
p.cancel('2s later end');
}, 2000);
}
test2(); // result: 2s later end
複製代碼
你覺得這樣就結束了嗎?第四個問題咱們尚未解決,既然問了這麼問題,那必然是有緣由的。異步
當sleep暫停時間尚未結束前,咱們中斷了sleep函數,setTimeout函數其實還佔用着內存,致使內存泄露,因此咱們須要將定時器在執行cancel的時候取消掉。
function sleep(timeout) {
var res,timer;
var promise = new Promise(function (resolve) {
res = resolve;
timer = setTimeout(function () {
resolve('done');
}, timeout);
});
var cancel = function (data) {
res(data);
clearTimeout(timer)
}
promise.cancel = cancel;
return promise;
}
複製代碼
到此,支持中斷的sleep函數書寫完畢,你看廢了嗎? 接下來我將ts版的實現貼出來,僅供你們參考,如何有更好的實現,能夠在留言區告訴我。
type CancelablePromise = Promise<any> & { cancel: any }
function sleep(timeout: number): CancelablePromise {
let res: (v: string) => void, timer: NodeJS.Timer;
let promise = new Promise(resolve => {
res = resolve
timer = setTimeout(() => {
resolve('done')
}, timeout)
}) as CancelablePromise
let cancel = function (data: string) {
res(data)
clearTimeout(timer)
}
promise.cancel = cancel;
return promise
}
export default sleep;
複製代碼
今天是2020年6月1日兒童節,祝各位大朋友、小朋友,今天只作小孩,保持咱們的童心,敢作夢、敢實現。
關注個人公衆號(全棧碼農)或加我wx(w34638660),和我一塊兒成長。