摘要:高級定時器高級技巧異步首先,中沒有代碼是立即執(zhí)行的,而是一旦進程空閑則立即執(zhí)行。針對第二種問題,使用定時器是解決方法之一。為定時器設(shè)定的時間間隔使得進程有時間在處理項目的事件之間轉(zhuǎn)入空閑。該函數(shù)首先清除之前設(shè)置的任何定時器。
title: 高級定時器
date: 2016-12-13
tag: JS高級技巧
首先,JavaScript 中沒有代碼是立即執(zhí)行的,而是一旦進程空閑則立即執(zhí)行。
進程何時空閑,取決于上一個執(zhí)行隊列的執(zhí)行時間,而與此對應(yīng)的是隨著頁面中生命周期的推移而產(chǎn)生的代碼執(zhí)行順序隊列。
定時器對隊列的工作方式是,當設(shè)定的時間過去以后將代碼插入隊列,但不代表代碼會被立即執(zhí)行。
0x01 重復(fù)定時器很多情況下,我們都需要使用 setInterval() 重復(fù)的執(zhí)行同一段代碼去做同一件事情,而在這時,最大的問題在于定時器可能在代碼再次被添加到隊列之前還沒有被執(zhí)行完成,從而導(dǎo)致某些間隔被跳過或者多個定時器的代碼執(zhí)行時間間隔被縮短。
為了避免以上缺點,可以使用鏈式調(diào)用 setTimeout() 模式
setTimeout(function(){ // do something setTimeout(arguments.callee, interval); }, interval)
一個例子:
setTimeout(function(){ $("#block").css({ "left": $("#block").position().left -1, }) if($("#block").position().left > 0){ setTimeout(arguments.callee, 30); } }, 30)0x01 數(shù)組分塊
為了防止惡意程序猿將用戶的計算機搞掛,瀏覽器對 JavaScript 能夠使用的資源進行了限制,如果代碼的運行時間超過特定時間或者特定語句數(shù)量就不讓其繼續(xù)運行。
而腳本運行時間過長的兩個主要原因是:1)過長,過深嵌套的函數(shù)調(diào)用;2)進行大量處理的循環(huán)。
針對第二種問題,使用定時器是解決方法之一。使用定時器分隔循環(huán),是一種叫作 數(shù)組分塊(array chunking) 的技術(shù)。
在數(shù)組分塊模式中,array 變量本質(zhì)上就是一個 “代辦事項” 列表,它包含了要處理的項目,而 shift() 可以獲取隊列中下一個要處理的項目,然后將其傳遞個某個函數(shù)。當隊列中還剩下其它項目時,則設(shè)置另一個定時器,并通過 arguments.callee 調(diào)用同一個匿名函數(shù)。
function chunk(array, process, context){ setTimeout(function(){ var item = array.shift() process.call(context, item) if(array.length > 0){ setTimeout(arguments.callee, 100) } }, 100) }
chunk() 方法接收三個參數(shù): 要處理項目的數(shù)組,用于處理項目的函數(shù),可選的運行該函數(shù)的環(huán)境。
在函數(shù)內(nèi)部,通過 call() 調(diào)用 process() 函數(shù),這樣可以設(shè)置一個合適的執(zhí)行環(huán)境。為定時器設(shè)定的時間間隔使得 JavaScript 進程有時間在處理項目的事件之間轉(zhuǎn)入空閑。
調(diào)用實例:
var data = [12,124,343,56,76767,43,654,34645,56456,767,4645] function printValue(item){ var div = $("#block").html() $("#block").html(div + item + "
") } chunk(data, printValue)
如上,函數(shù) printValue() 將 data 數(shù)組中的每個值輸出到一個 div 元素中。由于函數(shù)處于全局作用域中,因此無需給 chunk() 函數(shù)傳遞 context 對象。
如果想保持原數(shù)組不變,則應(yīng)將該數(shù)組的克隆傳遞給 chunk()
chunk(data.concat(), printValue)
調(diào)用某個數(shù)組的.contact(),如果不傳遞任何參數(shù),將返回和原來數(shù)組中項目一樣的數(shù)組。
0x02 函數(shù)節(jié)流函數(shù)節(jié)流 的基本思想是指,某些代碼不可以在沒有間斷的情況下連續(xù)重復(fù)的執(zhí)行。
瀏覽器中某些計算和處理的代價要比其他的昂貴很多,比如,DOM 操作比非 DOM 交互需要更多的內(nèi)存和 CPI 時間,而進行過多的 DOM 相關(guān)操作可能導(dǎo)致瀏覽器掛起甚至崩潰,對于這種問題,可以使用定時器對函數(shù)進行節(jié)流。
函數(shù)節(jié)流的基本模式可以簡化如下:
function throttle(method, context){ clearTimeout(method.tId) method.tId = setTimeout(function(){ method.call(context) }, 100) }
throttle() 函數(shù)接收兩個參數(shù): 要執(zhí)行的函數(shù)以及在哪個作用域中執(zhí)行。該函數(shù)首先清除之前設(shè)置的任何定時器。定時器 ID 是存儲在函數(shù)的 tId 屬性中的,當然,首次將方法傳遞給 throttle 函數(shù)可能并不存在該屬性。然后定義一個新的定時器,并將 ID 存儲在 tId 屬性中。而 call() 用來確保方法在適當?shù)沫h(huán)境中執(zhí)行。如果沒有給出第二個參數(shù),那么就在全局作用域內(nèi)執(zhí)行該方法。
在 setTimeout() 中用到的函數(shù)其執(zhí)行環(huán)境總是 window
throttle 方法調(diào)用實例:
function resizeDiv(){ var div = document.querySelector("#block") div.style.height = div.offsetWidth + "px" } window.onresize = function(){ throttle(resizeDiv) }
如上,為了保證在 resize 事件中瀏覽不會進行高頻率,或者多次計算,我們給 window.onresize 綁定了一個函數(shù),在該函數(shù)調(diào)用了 throttle 方法,從而在窗口大小發(fā)生改變的時候是 div#block 的高度與其寬度保持一致。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/91349.html
摘要:圖二解讀定時器可以在指定時間把定時器代碼加入待執(zhí)行隊列,但并不能保證代碼執(zhí)行時機,待執(zhí)行隊列中的代碼要等進程空閑時才能執(zhí)行。也就是說定時器每隔間隔觸發(fā)一次,嘗試加入隊列,擁堵時段將直接忽略本次操作。 圖片出自JS高程(第三版) showImg(https://segmentfault.com/img/bVbgC3V?w=1337&h=313); 圖一解讀:JS運行于單線程的環(huán)境中:頁面...
摘要:關(guān)于定時器要記住的最重要的事情是指定的時間間隔表示何時將定時器的代碼添加到隊列,而不是何時實際執(zhí)行代碼。多個定時器之間的執(zhí)行間隔會比預(yù)期的小解決辦法處理中數(shù)組分塊,,函數(shù)節(jié)流,實際進行處理的方法實際執(zhí)行的代碼初始處理調(diào)用的方法 一、高級函數(shù) 安全類型檢測 Object.protitype.toString.call(value) 作用域安全的構(gòu)造函數(shù) function Pers...
摘要:下面通過幾個的定時器示例以及相關(guān)源碼來分析在中,功能到底是怎么實現(xiàn)的。我們知道,中的定時器并不同于計算機底層的定時中斷。補充資料在高級程序設(shè)計第三版第章高級技巧中對高級定時器以及有較詳細的討論。至此,這類定時器函數(shù)已經(jīng)可以為所用了。 上一篇博文提到,在Node中timer并不是通過新開線程來實現(xiàn)的,而是直接在event loop中完成。下面通過幾個JavaScript的定時器示例以及N...
摘要:和的定義是指多少時間之后將回調(diào)函數(shù)加入到的執(zhí)行隊列之中回調(diào)函數(shù)是否立即執(zhí)行取決于當前的執(zhí)行隊列是否空閑。比較好的例子如下回調(diào)函數(shù)執(zhí)行其他操作假如內(nèi)部的執(zhí)行時間為那么的回調(diào)函數(shù)至少要等待才執(zhí)行。 1、惰性加載函數(shù) (判斷各個瀏覽器中是否支持某個屬性) function addEvent(elem, type, handler){ if(elem.addEventListener...
摘要:閉包閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)當某個函數(shù)被調(diào)用時,會創(chuàng)建一個執(zhí)行環(huán)境及相應(yīng)的作用域鏈。要注意通過第句聲明的這個方法屬于構(gòu)造函數(shù)生成的對象,而不屬于構(gòu)造函數(shù)的變量對象,也就是說,并不存在于作用域鏈中。 看到評論里有仁兄建議我試試箭頭函數(shù),真是受寵若驚,本來寫這篇文章也只是想記錄寫要點給自己日后看的。今天早上看到一篇總結(jié)javascript中this的文章JavaScr...
閱讀 749·2021-10-14 09:43
閱讀 2072·2021-09-30 09:48
閱讀 3440·2021-09-08 09:45
閱讀 1090·2021-09-02 15:41
閱讀 1878·2021-08-26 14:15
閱讀 770·2021-08-03 14:04
閱讀 2972·2019-08-30 15:56
閱讀 3072·2019-08-30 15:52