首頁 web前端 js教程 深入探索javascript計時器_javascript技巧

深入探索javascript計時器_javascript技巧

May 16, 2016 pm 04:22 PM
javascript 定時器

javascript單線程

JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單線程,否則會帶來複雜的同步問題。例如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上加入內容,另一個線程就刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?所以,為了避免複雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵,未來也不會改變。

隊列任務

單執行緒就意味著,所有任務都需要排隊,前一個任務結束,才會執行後一個任務。如果前一個任務耗時很長,後一個任務就得一直等著。


非同步事件驅動

瀏覽器中許多行為是非同步(Asynchronized)的,例如:滑鼠點擊事件、視窗大小拖曳事件、計時器觸發事件、XMLHttpRequest完成回調等。當一個非同步事件發生的時候,它就會進入事件佇列。瀏覽器有一個內部大消息循環,Event Loop(事件循環),會輪詢大的事件佇列並處理事件。例如,瀏覽器目前正忙於處理onclick事件,這時另外一個事件發生了(如:window onSize),這個非同步事件就被放入事件佇列等待處理,只有前面的處理完畢了,空閒了才會執行這個事件。

Event Loop

JavaScript是單執行緒的,但瀏覽器不是單執行緒的

瀏覽器至少會有以下一些進程

1.瀏覽器 GUI 渲染線程

2.JavaScript 引擎執行緒

3.瀏覽器定時觸發器執行緒

4.瀏覽器事件觸發執行緒

5.瀏覽器 http 非同步請求執行緒

因為 JavaScript 引擎是單執行緒的,所以程式碼都是先壓到佇列,然後由引擎採用先進先出的方式運作。事件處理函數、timer 執行函數也會排到這個佇列中,然後利用一個無窮迴圈,不斷從隊頭取出函數執行,這就是Event Loop。

總結一句話,js是單線程的,但是瀏覽器是多線程的,遇到異步的東西都是由瀏覽器把異步的回調放到Event Loop中,js線程不繁忙的時候,再去讀取Event Loop

定時器原理

定時器的用法

setTimeout(fn, delay)

setInterval(fn, delay)

fn是函數也可以是字串,delay是延遲的時間,單位是毫秒

有以下要注意的

1.fn雖然可以是字串,但是一直都不推薦這麼使用

2.fn裡面的函數如果有this,執行的時候this會指向到window上面去


如果理解好了js單線程和Event loop,定時器的原理也很好理解了

如果設定了定時器,當到了延遲時間,瀏覽器會把延遲執行的事件放到Event loop裡面,當時間到了,如果js線程空閒就會執行了(所以定時器的精度不準啊)


看有文章介紹說setTimeout和setInterval對函數一直輪詢的區別,程式碼如下

複製程式碼 程式碼如下:

        setTimeout(function(){
            setTimeout(arguments.callee,100)   
        },100)
        setInterval(function(){},1000)

文章大概的意思是setTimeout是在回調函數執行後才啟動下一次定時器,所以肯定是有間隔的執行,而setInterval是一直都在執行,如果碰到了js線程一直執行,可能就會在Event loop裡面加多個回呼,當js執行緒不忙的時候,會一下子執行多個

經過測試發現無論在ie,ff,chrome,Opera,Safari下,setInterval都是以一定間隔來的

測試程式碼如下

複製程式碼 程式碼如下:

        setInterval(function(){
            xx.innerHTML=xx.innerHTML 1;
        },100);
       
        for(var i=0;i             xx.offsetWidth
        }

        setTimeout(function(){
            debugger;
        },10)

斷點的時候還是只印出了1個1

定時器的精確度問題

因為js單線程原因,如果遇到繁忙,定時器肯定不準,而且肯定是越來越長的,這個好像無解啊,無解啊

還有一個精確度問題就是最小間隔setTimeout(fun,0)

在js執行緒不忙的時候,也不可能0秒後馬上執行,總有個最小間隔,每個瀏覽器還各不一樣,這個未做測試

我看一篇文章中說的是w3c的標準,定時器的最小時間執行是4ms,找不到出處無從考證呀! ! !

定時器相關的一些最佳化

在做定時器的時候還是可以有一些最佳化的

1.例如如果綁定window.onresize,在瀏覽器縮放的時候,該觸發的非常頻繁,所以可以延遲執行,當下次執行到的時候clear掉,減少頻繁執行

 偽代碼如下

複製程式碼 程式碼如下:

    var timer;
    function r(){
        clearTimeout(timer);
        timer = setTimeout(function(){
            //do something
        },150);       
    }

2.在滾動條往下拉的時候也是一下,比如圖片的lazyload,也應該有一個定時器,避免過多的計算

3.當有多個地方需要定時器的時候,可以合併成一個定時器,時間間隔以最小的那個為準,然後需要執行的回調函數往數組裡面塞,當到了時間間隔,遍歷數組執行即可

 一個小demo

複製程式碼 程式碼如下:




   
   



   

       
0

       
0

       
0

       
0

   

>
   
        var runTime = {
            選項:{
                步驟:1000
            },
            回調:[],
            addCallbacks : [],
            開始:假,
            計時器:空,
            擴充:函數(){
                var 目標 = 參數[0] || {},i = 1,長度=arguments.length,選項;
                if ( typeof target != "object" && typeof target != "function" )
                    目標 = {};
                為 ( ; i                     if ( (options = argument[ i ]) != null )
                        for ( 選項中的 var 姓名 ) {
                            var copy = options[姓名 ];
                            if ( 目標 === 複製 )
                                續中;
                           if (複製!==未定義)
                               , 目標[姓名]=複製;
                        }
                回復目標;
            },
            初始化:函數(選項){
                $.extend(this,this.options,options||{});
            },
            新增:功能(樂趣,選項){
                選項 = 選項 ||{};
                this.addCallbacks.push({
                    有趣       : 有趣,
                    startTime : new Date().getTime(),
                    步驟     : options.step ||此一步,
                    我        : 1
                });
                var self = this;
                if(!this.start){
                    this.callbacks = [有趣];
                    this.start = true;
                    this.startTime = new Date().getTime();
                    this.timer = setInterval(function(){
                        self.done();   
                      
                    },此步驟);
                }
            },
            完成:函數(){
                varcallbacks = this.callbacks,
                    自我=這個,
                    newArr = [];
                $.each(回呼,函數(i,obj){
                    if(obj.step == self.step){
                        obj.fun();
                    }否則{                                          if(obj.i == obj.step/self.step){
                            if((new Date().getTime())-obj.startTime>obj.step*2/3){
                               obj.fun();
;
;                             }
                            obj.i = 1;
                        }其他{
                            obj.i = obj.i 1;
                        }
                    }
                });
                $.each(this.addCallbacks,function(i,obj){
                    if(obj.step == self.step){
                        if((new Date().getTime())-obj.startTime>obj.step*2/3){
                           obj.fun();
                            回復.push(obj);
                        }其他{
                            newArr.push(obj);
                        }
                    }其他{
                        obj.i = obj.i 1;
                        回復.push(obj);
                    }
                });
                this.addCallbacks = newArr;
            },
            清除:函數(){
                clearInterval(this.timer);
            }
        }
        runTime.init();

        runTime.add(function(){
            a1.innerHTML = ~~a1.innerHTML 1;
        });

        runTime.add(function(){
            a2.innerHTML = ~~a2.innerHTML 1;
        },{步驟:2000});

        runTime.add(function(){
            a3.innerHTML = ~~a3.innerHTML 1;
        },{步長:4000});
                runTime.add(function(){
            a4.innerHTML = ~~a4.innerHTML 1;
        },{步長:8000});
    腳本>
身體>

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

java定時器表達式是什麼 java定時器表達式是什麼 Dec 27, 2023 pm 05:06 PM

定時器的表達式用於定義任務的執行計劃。定時器的表達式是基於「在給定的時間間隔之後執行任務」的模型。表達式通常由兩個部分組成:一個初始延遲和一個時間間隔。

See all articles