前端開發:setTimeout與setInterval 定時器與異步循環數組


            前端開發:setTimeout與setInterval 定時器與異步循環數組

前言:

  開通博客園三個月以來,隨筆記錄了工作中遇到的大大小小的難題,也看過無數篇令人啟發的文章,我覺得這樣的環境是極好的,在與博友的分享中可以學到新的知識、得到先驅者的指正、解決工作中遇到的難題。近一個月工作繁忙,新的文章也遲遲未寫,今天呢,過來深入了解一下 關於javascript定時器的知識;

setTimeout與setInterval簡述

  

setTimeout與setInterval使用方法基本相同,他們接受兩個參數,第一個參數是需要執行的函數,第二個參數是執行的延遲時間,看栗子:

setTimeout(function(){
    alert("hello");  //第一個參數為函數 你可以傳入函數名 或一個匿名函數
},3000);       //第二個參數為延遲時間  標識多少毫秒之后執行前一個函數

setInterval(function(){
    alert("hello");
},3000);

 

setTimeout與setInterval唯一不同的是,setTimeout在指定的延遲時間到達后 向ui隊列添加一個任務,函數會立即執行,setInterval則是在指定的延遲時間不斷的向ui隊列添加執行任務,如果你沒有手動清除那么setInterval就會一直執行下去,直到頁面被關閉,如果ui隊列中存在由同一個setInterval創建的任務,那么后續任務將不會被添加到ui隊列中。

通俗的說就是,讓一個函數在指定時間之后再執行,和讓一個函數在指定時間一直執行;

然而它在實際項目中有什么作用呢,我們可以利用setInterval制作定時幻燈片、實時數據更新、新聞列表滾動、jQuery的.animate()方法就是依靠定時器模擬動畫效果;此博客實現了這一代碼,貼在下面與大家一起討論:  http://www.cnblogs.com/slowsoul/archive/2013/02/21/2921354.html   JavaScript——創建運動框架

 

 

提到定時器,就不得不先介紹一個JavaScript運行機制--》瀏覽器UI線程

用於執行javascript和更新用戶界面的進程通常被稱為“瀏覽器UI線程”

  在瀏覽器中,Javascript執行與UI更新是發生在同一個進程(瀏覽器UI線程)中的。UI線程的工作基於一個簡單的隊列系統,任務會被保存到隊列 中直到進程空閑時被提取出來執行。所以Javascript的執行會阻塞UI更新;反之,UI更新也會阻塞Javascript的執行。給用戶的表現就是 瀏覽器在工作時短暫或長時間失去反應,用戶的操作不能及時得到響應。而UI線程的阻塞很多時候是由於我們要在代碼里進行長時間的腳本運算,超過了瀏覽器限 制,導致瀏覽器失去響應,凍結用戶界面。傳送門: Javascript之UI線程與性能優化

使用定時器可以異步處理需要大量運算的任務,它可以適時的避免ui更新與javascript執行之間的沖突

例如在某種極端環境下:

for(var i=0;i<5000;i++){
    document.body.innerHTML += "hello"+i;
}

 

這段代碼向body插入字符串   持續運行了五千次,在谷歌瀏覽器中這段代碼會執行3秒左右 而這段時間頁面始終是空白且不可操作的,這是一個非常常見的性能問題,在處理大量運算的時候,我們可以利用延遲執行將代碼分成幾段分別運行,可以有效改善代碼執行速度,並且因為它是異步的 在執行中的空隙,ui會啟動更新,因此並不會導致頁面空白,用戶體驗提高;

 

setTimeout(function(){
    for(var i=0;i<2500;i++){
        document.body.innerHTML += "hello"+i;
    }
//分段處理 五千次分成兩段 setTimeout(
function(){ for(var i=0;i<2500;i++){ document.body.innerHTML += "hello"+i; } },100); },100);

 

 

 

 

假如向服務器請求一個超長的新聞列表,由於數據量過去龐大,單個循環解析數據持續時間過長,那么可以使用定時器分解任務,異步處理數據

一般情況下,我們處理數據都是這樣的:

for(var i=0,len=msg.length;i<len;i++){
 process(msg[i])       
}

一般我們使用for或者while循環解析數據, 這樣的問題是 在執行完成之前我們是沒有辦法控制頁面的,數據越龐大越明顯

 

使用定時器分解任務

使用定時器分解任務有兩個前提

  1.數據的處理不需要按照特定的順序

  2.是否必須同步處理,如果必須同步處理那么定時器不適用;

其核心理論是,每間隔一段時間(通常是30毫秒,視情況而定)執行當前項的處理函數;

封裝之后的代碼:

volist:function(name,id,callback,time){
//settimeout 異步循環 name為需要循環的array對象 id為要執行的解析函數  time設置每次運行的時間
        if(time==undefined){time=30;};
        var fattr = name.concat();//克隆數組
        setTimeout(function(){
            if(fattr.length>0){
                id(fattr.shift());  //執行每一個數組項運行的函數
                setTimeout(arguments.callee,time);
            }else{
                callback();//執行結束 回調函數
            }
        },time);//異步調用時間  默認30 
    }

 

還有另一種使用方式,將函數放在數組里,異步循環調用,將要執行的多個任務拆分成不同的子任務,分階段分別執行:

function fun1(){
    alert(1)
}
function fun2(){
    alert(2)
}
function fun3(){
    alert(3)
}
var farr = [fun1,fun2,fun3];  //將任務存儲到數組中 setTimeout(function(){ if(farr.length>0){ var func=farr.shift(); //取出 func(); //執行函數 setTimeout(arguments.callee,300); }else{ alert("執行完成") }
},
300); //300秒執行一次

 

定時器的性能問題

  需要注意的是,當一個頁面中存在多個定時器,他們執行的任務過多,往往會導致不可預料的問題;解決方法就是盡量避免創建多個定時器,只創建一個獨立的定時器,讓它分別執行不同的任務,另外每次調用setInterval()之前應清除前面已經無用的setInterval,或者是防止重復指定setInterval

var timer
//先清除
clearInterval(timer);
//再調用
  timer = setInterval(function(){
    ......
},5000);

 

總結

  合理使用定時器無疑能夠增加頁面的整體性能,在處理不需要同步,不需要順序執行的任務時,可以考慮使用setTimeout代替for循環  異步處理任務;

 

---------------------------------------時間不曾停下它的腳步,你又怎么可以止步不前---------------------------------------

 

  我的微信號:    qq:

 歡迎各種技術討論,如果您有建站需求,歡迎聯系;

 (轉載請注明出處)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM