JavaScript 提供定時執行代碼的功能,叫作 定時器(timer)。ajax
主要由 setTimeout() 和 setInterval() 這兩個函數來完成。它們向任務隊列添加定時任務瀏覽器
var timerId = setTimeout( func()|code, delay);
第一個參數 func() | code 是將要推遲執行的函數名或者一段代碼服務器
第二個參數 delay是推遲執行的毫秒數app
console.log(1); setTimeout('console.log(2)',1000); console.log(3); // 1 // 3 // 2
上面代碼會 先輸出 1 和 3,而後等待 1000毫秒 再輸出 2函數
function f() { console.log(2); } setTimeout(f, 1000);
setTimeout(function (a,b) { console.log(a + b); }, 1000, 1, 1); // 1秒鐘後打印 '2'
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(obj.y, 1000); // 1 打印的是全局變量 x
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(function () { obj.y(); }, 1000); // 2 打印的是 obj 對象的屬性 x
var x = 1; var obj = { x: 2, y: function () { console.log(this.x); } }; setTimeout(obj.y.bind(obj), 1000)
var aDiv = document.getElementById('a_div'); var opacity = 1; var flag = true; var brath = setInterval(function() { if (opacity >= 0 && flag ) { opacity -= 0.1; } else { opacity += 0.1; } aDiv.style.opacity = opacity; if(opacity < 0 || opacity > 1){ flag = !flag; } }, 200);
上面代碼是讓一個div 透明度慢慢下降,而後又慢慢增高。。。呼吸的效果性能
var hash = window.location.hash; var hashWatcher = setInterval(function() { if (window.location.hash != hash) { updatePage(); } }, 1000);
var i = 1; var timer = setTimeout(function f() { // ... timer = setTimeout(f, 2000); // 能夠確保,下一次執行老是在本次執行結束以後的2000毫秒開始 }, 2000);
var id1 = setTimeout(f, 1000); var id2 = setInterval(f, 1000); clearTimeout(id1); clearInterval(id2); // 上面代碼中,回調函數f不會再執行了,由於兩個定時器都被取消了
function f() {} setTimeout(f, 1000); // 10 setTimeout(f, 1000); // 11 setTimeout(f, 1000); // 12
(function() { var gid = setInterval(clearAllTimeouts, 0); function clearAllTimeouts() { var id = setTimeout(function() {}, 0); while (id > 0) { if (id !== gid) { clearTimeout(id); } id--; } } })();
先調用setTimeout
,獲得一個計算器編號,而後把編號比它小的計數器所有取消this
$('textarea').on('keydown', ajaxAction);
這樣寫有一個很大的缺點,就是若是用戶連續擊鍵,就會連續觸發keydown
事件,形成大量的 Ajax 通訊。spa
// 假定兩次 Ajax 通訊的間隔不得小於2500毫秒,上面的代碼能夠改寫成下面這樣 $('textarea').on('keydown', debounce(ajaxAction, 2500)); function debounce(fn, delay){ var timer = null; // 聲明計時器 return function() { var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); }; }
只要在2500毫秒以內,用戶再次擊鍵,就會取消上一次的定時器,而後再新建一個定時器。這樣就保證了回調函數之間的調用間隔,至少是2500毫秒code
setTimeout(someTask, 100); veryLongTask(); // 上面代碼的setTimeout,指定100毫秒之後運行一個任務。 // 可是,若是後面的veryLongTask函數(同步任務)運行時間很是長,過了100毫秒還沒法結束,那麼被推遲運行的someTask就只有等着,等到veryLongTask運行結束,才輪到它執行
setInterval
的例子
setInterval(function () { console.log(2); }, 1000); sleep(3000); function sleep(ms) { var start = Date.now(); while ((Date.now() - start) < ms) { } }
// 上面代碼中,setInterval要求每隔1000毫秒,就輸出一個2。
// 可是,緊接着的sleep語句須要3000毫秒才能完成,那麼setInterval就必須推遲到3000毫秒以後纔開始生效。
// 注意,生效後setInterval不會產生累積效應,即不會一會兒輸出三個2,而是隻會輸出一個2。
setTimeout(function () { console.log(1); }, 0); console.log(2); // 2 // 1
上面代碼先輸出2,再輸出1。由於2是同步任務,在本輪事件循環執行,而1是下一輪事件循環執行對象
// HTML 代碼以下 // <input type="button" id="myButton" value="click"> var input = document.getElementById('myButton'); input.onclick = function A() { setTimeout(function B() { input.value +=' input'; }, 0) }; document.body.onclick = function C() { input.value += ' body' };
上面代碼在點擊按鈕後,先觸發回調函數 A ,而後觸發函數 C 。
函數 A 中,setTimeout() 將函數 B() 推遲到下一輪事件循環執行,這樣就起到了,先觸發父元素的 回調函數 C() 的目的了
// HTML 代碼以下 // <input type="text" id="input-box"> document.getElementById('input-box').onkeypress = function (event) { this.value = this.value.toUpperCase(); }
// 上面代碼想在用戶每次輸入文本後,當即將字符轉爲大寫。
// 可是實際上,它只能將本次輸入前的字符轉爲大寫,
// 由於瀏覽器此時還沒接收到新的文本,因此 this.value 取不到最新輸入的那個字符
document.getElementById('input-box').onkeypress = function() { var self = this; setTimeout(function() { self.value = self.value.toUpperCase(); }, 0); }
上面代碼將代碼放入setTimeout之中,就能使得它在瀏覽器接收到文本以後觸發
var div = document.getElementsByTagName('div')[0]; // 改變一個網頁元素的背景色 寫法一 會形成瀏覽器「堵塞」 由於 JavaScript 執行速度遠高於 DOM,會形成大量 DOM 操做「堆積」 for (var i = 0xA00000; i < 0xFFFFFF; i++) { div.style.backgroundColor = '#' + i.toString(16); } // 改變一個網頁元素的背景色 寫法二 的好處,解決了上面的問題 var timer; var i=0x100000; function func() { timer = setTimeout(func, 0); div.style.backgroundColor = '#' + i.toString(16); if (i++ == 0xFFFFFF){ clearTimeout(timer); } } timer = setTimeout(func, 0);setTimeout(f, 0)