頁面中實(shí)現(xiàn)setInterval和setTimeout效果示例詳解
前言
昨天面試一家公司,面試官問我,如何在不使用setTimeout和setInterval在頁面中實(shí)現(xiàn)setInterval和setTimeout效果,我:????。
后來我仔細(xì)想了一下,思路就是獲取時(shí)間戳,然后用遞歸判斷實(shí)現(xiàn)。那么思路是這樣,下面就代碼實(shí)現(xiàn)一下吧。
setTimeout的實(shí)現(xiàn)
function setTimeout_(dalay) {
// 第一次的時(shí)間戳
const timestampFirst = Date.now()
// 返回一個(gè)promise對象
return new Promise(reslove => {
// 操作
function handle() {
// 每一次的時(shí)間戳
const timestamp = Date.now()
// 當(dāng)時(shí)間戳減去后大于延遲時(shí)間
if ((timestamp - timestampFirst) >= dalay) {
// 成功回調(diào)
reslove()
} else {
// 遞歸
handle()
}
}
// 初次調(diào)用
handle()
})
}
setTimeout_(10).then(() => {
alert(10)
})
上面的代碼看似沒有毛病,但是運(yùn)行后發(fā)現(xiàn),setTimeout_()里面的值設(shè)置小一點(diǎn)沒有問題(比如2、3),但是一旦超過,就會(huì)造成堆棧溢出,乃至報(bào)錯(cuò)。
解決堆棧溢出方法
下面隆重介紹一個(gè)人,蹦床函數(shù)(trampoline)
蹦床函數(shù)(trampoline)就是將 遞歸執(zhí)行 轉(zhuǎn)為 循環(huán)執(zhí)行。
執(zhí)行的都是同樣的步驟,只是反復(fù)執(zhí)行,就好像在蹦床,跳上去,掉下來,在跳上去…
- 蹦床函數(shù)的實(shí)現(xiàn):
function trampoline(f){
while(f && f instanceof Function && falg){
f = f()
}
return f
}
它接受一個(gè)函數(shù)f作為參數(shù)。只要f執(zhí)行后返回一個(gè)函數(shù),就繼續(xù)執(zhí)行。注意,這里是返回一個(gè)函數(shù),然后執(zhí)行該函數(shù),而不是函數(shù)里面調(diào)用函數(shù),這樣就避免了遞歸執(zhí)行,從而就消除了調(diào)用棧過大的問題
最終實(shí)現(xiàn)
// 定時(shí)器
function setTimeout_(dalay) {
// 第一次的時(shí)間戳
const timestampFirst = Date.now()
// 返回一個(gè) Promise 對象
return new Promise(reslove => {
// 具體操作
function handle() {
// 每一次的時(shí)間戳
const timestamp = Date.now()
// 當(dāng)時(shí)間戳減去后大于延遲時(shí)間
if ((timestamp - timestampFirst) >= dalay) {
// 成功回調(diào)
reslove()
} else {
// 不滿足條件繼續(xù)調(diào)用
return handle
}
}
// 調(diào)用蹦床函數(shù)、將遞歸變?yōu)檠h(huán)
trampoline(handle)()
})
}
// 蹦床函數(shù)
function trampoline(f){
while(f && f instanceof Function){
f = f()
}
return f
}
setTimeout_(1000).then(res => {
alert(1000)
})
以上的代碼,就能實(shí)現(xiàn)效果了
思路:定義一個(gè)函數(shù),參數(shù)為延遲時(shí)間,調(diào)用時(shí)記錄一個(gè)第一次時(shí)間戳,然后里面返回一個(gè)Promise對象,再里面有一個(gè)閉包,是執(zhí)行遞歸操作的函數(shù),這個(gè)函數(shù)里面做的事就是記錄每一次的時(shí)間戳,然后減去第一次的時(shí)間戳,得出的就是間隔時(shí)間,跟規(guī)定的間隔時(shí)間作比較,如果大于的話,就調(diào)用Promise成功回調(diào)。再下面就是將遞歸轉(zhuǎn)為循環(huán),防止堆棧溢出。最后調(diào)用
setInterval的實(shí)現(xiàn)
這個(gè)跟setTimeout差不多,區(qū)別就是這個(gè)需要每隔一段時(shí)間執(zhí)行代碼,并且需要手動(dòng)清除
// 如果 falg 為 false就不會(huì)繼續(xù)執(zhí)行循環(huán)操作
let falg = true
// 蹦床函數(shù)技術(shù),利用循環(huán)
function trampoline(f){
while(f && f instanceof Function && falg){
f = f()
}
return f
}
// 計(jì)時(shí)器
function setInterval_(f, dalay) {
// 第一次的時(shí)間戳
let timestampFirst = Date.now()
// 操作
function handle() {
// 每一次的時(shí)間戳
const timestamp = Date.now()
if ((timestamp - timestampFirst) >= dalay) {
// 間隔時(shí)間到了就重置第一次時(shí)間戳
timestampFirst = Date.now()
// 調(diào)用函數(shù)
f()
}
return handle
}
trampoline(handle)()
}
let count = 0
// 調(diào)用
setInterval_(function() {
count ++
if (count === 3) {
falg = false
}
console.log(count)
}, 1000)
上面這個(gè)代碼我定義的是在控制臺(tái)輸入1、2、3,然后關(guān)閉
思路:同樣是判斷時(shí)間戳,但是跟setTimeout不一樣的是每次執(zhí)行里面的函數(shù)需要重置時(shí)間,達(dá)到每次執(zhí)行的效果。并且在蹦床函數(shù)里面的while增加一個(gè)判斷,用來控制計(jì)時(shí)器的停止。
總結(jié):這種東西了解一下,以后當(dāng)個(gè)吹牛逼資本就可以了,畢竟這性能嘛.....

以上就是頁面中實(shí)現(xiàn)setInterval和setTimeout效果示例詳解的詳細(xì)內(nèi)容,更多關(guān)于setInterval setTimeout頁面效果的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript 組件之旅(二)編碼實(shí)現(xiàn)和算法
話說上期我們討論了隊(duì)列管理組件的設(shè)計(jì),并且給它取了個(gè)響亮而獨(dú)特的名字:Smart Queue. 這次,我們要將之前的設(shè)計(jì)成果付諸實(shí)踐,用代碼來實(shí)現(xiàn)它。2009-10-10
微信公眾平臺(tái) 發(fā)送模板消息(Java接口開發(fā))
這篇文章主要介紹了微信公眾平臺(tái) 發(fā)送模板消息(Java接口開發(fā)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
微信小程序中實(shí)現(xiàn)雙向綁定的實(shí)戰(zhàn)過程
最近在小程序的開發(fā)過程中,需要用到雙向綁定,遇到報(bào)錯(cuò)才知道微信本身是不支持對象雙向綁定的,折騰一番找到解決方案,下面這篇文章主要給大家介紹了關(guān)于微信小程序中實(shí)現(xiàn)雙向綁定的相關(guān)資料,需要的朋友可以參考下2023-01-01
讓瀏覽器非阻塞加載javascript的幾種方法小結(jié)
通常大多數(shù)瀏覽器是并行下載資源的,但由于外部腳本的特殊性例如通過腳本改變文檔的DOM結(jié)構(gòu)、腳本之間的存在依賴關(guān)系、使用document.write 向頁面輸出HTML等。2011-04-04
tween.js緩動(dòng)補(bǔ)間動(dòng)畫算法示例
本篇文章主要介紹了tween.js緩動(dòng)補(bǔ)間動(dòng)畫示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02
JavaScript中常見的數(shù)據(jù)類型判斷方法小結(jié)
在?JS?編程中,正確判斷數(shù)據(jù)類型是必備技能,也是面試常問的內(nèi),本文將探討四種常用的數(shù)據(jù)類型判斷方法,通過了解它們的特點(diǎn)和適用范圍,能夠更好地處理不同數(shù)據(jù)類型的情況,避免出現(xiàn)錯(cuò)誤和提升代碼質(zhì)量,需要的朋友可以參考下2023-06-06

