亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

頁(yè)面中實(shí)現(xiàn)setInterval和setTimeout效果示例詳解

 更新時(shí)間:2022年09月15日 15:20:50   作者:來(lái)世做春風(fēng)  
這篇文章主要為大家介紹了不使用setTimeout和setInterval在頁(yè)面中實(shí)現(xiàn)setInterval和setTimeout效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

昨天面試一家公司,面試官問(wèn)我,如何在不使用setTimeout和setInterval在頁(yè)面中實(shí)現(xiàn)setInterval和setTimeout效果,我:????。

后來(lái)我仔細(xì)想了一下,思路就是獲取時(shí)間戳,然后用遞歸判斷實(shí)現(xiàn)。那么思路是這樣,下面就代碼實(shí)現(xiàn)一下吧。

setTimeout的實(shí)現(xiàn)

function setTimeout_(dalay) {
  // 第一次的時(shí)間戳
  const timestampFirst = Date.now()
  // 返回一個(gè)promise對(duì)象
  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)
})

上面的代碼看似沒(méi)有毛病,但是運(yùn)行后發(fā)現(xiàn),setTimeout_()里面的值設(shè)置小一點(diǎn)沒(méi)有問(wèn)題(比如2、3),但是一旦超過(guò),就會(huì)造成堆棧溢出,乃至報(bào)錯(cuò)。

解決堆棧溢出方法

下面隆重介紹一個(gè)人,蹦床函數(shù)(trampoline)

蹦床函數(shù)(trampoline)就是將 遞歸執(zhí)行 轉(zhuǎn)為 循環(huán)執(zhí)行。
執(zhí)行的都是同樣的步驟,只是反復(fù)執(zhí)行,就好像在蹦床,跳上去,掉下來(lái),在跳上去…

  • 蹦床函數(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)用棧過(guò)大的問(wèn)題

最終實(shí)現(xiàn)

// 定時(shí)器
function setTimeout_(dalay) {
  // 第一次的時(shí)間戳
  const timestampFirst = Date.now()
  // 返回一個(gè) Promise 對(duì)象
  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對(duì)象,再里面有一個(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è)判斷,用來(lái)控制計(jì)時(shí)器的停止。

總結(jié):這種東西了解一下,以后當(dāng)個(gè)吹牛逼資本就可以了,畢竟這性能嘛.....

以上就是頁(yè)面中實(shí)現(xiàn)setInterval和setTimeout效果示例詳解的詳細(xì)內(nèi)容,更多關(guān)于setInterval setTimeout頁(yè)面效果的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論