国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

異步操作(二)定時器

ctriptech / 2618人閱讀

摘要:提供定時執(zhí)行代碼的功能,叫做定時器,主要由和這兩個函數(shù)來完成。,利用這一點(diǎn),可以寫一個函數(shù),取消當(dāng)前所有的定時器。回調(diào)函數(shù)必須等本輪運(yùn)行完,因此時間不確定。另一個應(yīng)用是,用戶自定義的回調(diào)函數(shù),通常在瀏覽器的默認(rèn)動作之前觸發(fā)。

JavaScript 提供定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInterval()這兩個函數(shù)來完成。它們向任務(wù)隊列添加定時任務(wù)

setTimeout()
setInterval()
clearTimeout(),clearInterval()
實例:debounce 函數(shù)
運(yùn)行機(jī)制
setTimeout(f, 0)
含義
應(yīng)用

1.setTimeout()
執(zhí)行多少毫秒后執(zhí)行,返回一個編號(順序遞增),用于取消。
第一個參數(shù)func|code是將要推遲執(zhí)行的函數(shù)名或者一段代碼,第二個參數(shù)delay是推遲執(zhí)行的毫秒數(shù)。后面的參數(shù)為傳給回調(diào)函數(shù)的參數(shù)
setTimeout(function (a,b) {
console.log(a + b);
}, 1000, 1, 1);

This(回調(diào)函數(shù)為對象方法)為全局
var x = 1;

var obj = {
x: 2,
y: function () {

console.log(this.x);

}
};

setTimeout(obj.y, 1000) // 1
上面代碼輸出的是1,而不是2。因為當(dāng)obj.y在1000毫秒后運(yùn)行時,this所指向的已經(jīng)不是obj了,而是全局環(huán)境。

為了防止出現(xiàn)這個問題,一種解決方法是將obj.y放入一個函數(shù)。

var x = 1;

var obj = {
x: 2,
y: function () {

console.log(this.x);

}
};

setTimeout(function () {
obj.y();
}, 1000);
// 2
上面代碼中,obj.y放在一個匿名函數(shù)之中,這使得obj.y在obj的作用域執(zhí)行,而不是在全局作用域內(nèi)執(zhí)行,所以能夠顯示正確的值。

另一種解決方法是,使用bind方法,將obj.y這個方法綁定在obj上面。

var x = 1;

var obj = {
x: 2,
y: function () {

console.log(this.x);

}
};

setTimeout(obj.y.bind(obj), 1000)
//

2.setInterval()
setInterval指定某個任務(wù)每隔一段時間就執(zhí)行一次,也就是無限次的定時執(zhí)行。
下面是一個通過setInterval方法實現(xiàn)網(wǎng)頁動畫的例子。

var div = document.getElementById("someDiv");
var opacity = 1;
var fader = setInterval(function() {
opacity -= 0.1;
if (opacity >= 0) {

div.style.opacity = opacity;

} else {

clearInterval(fader);

}
}, 100);
上面代碼每隔100毫秒,設(shè)置一次div元素的透明度,直至其完全透明為止。
setInterval的一個常見用途是實現(xiàn)輪詢。下面是一個輪詢 URL 的 Hash 值是否發(fā)生變化的例子。

var hash = window.location.hash;
var hashWatcher = setInterval(function() {
if (window.location.hash != hash) {

updatePage();

}
}, 1000);

時間
不考慮執(zhí)行時間即會小于100ms ,第二次執(zhí)行就會開始。如果某次執(zhí)行耗時特別長,比如需要105毫秒,那么它結(jié)束后,下一次執(zhí)行就會立即開始。
為了確保兩次執(zhí)行之間有固定的間隔,可以不用setInterval,而是每次執(zhí)行結(jié)束后,使用setTimeout指定下一次執(zhí)行的具體時間。

var i = 1;
var timer = setTimeout(function f() {
// ...
timer = setTimeout(f, 2000);
}, 2000);
上面代碼可以確保,下一次執(zhí)行總是在本次執(zhí)行結(jié)束之后的2000毫秒開始。

3.clearTimeout(),clearInterval()
利用這一點(diǎn),可以寫一個函數(shù),取消當(dāng)前所有的setTimeout定時器。

(function() {
// 每輪事件循環(huán)檢查一次
var gid = setInterval(clearAllTimeouts, 0);

function clearAllTimeouts() {

var id = setTimeout(function() {}, 0);
while (id > 0) {
  if (id !== gid) {
    clearTimeout(id);
  }
  id--;
}

}
})();
上面代碼中,先調(diào)用setTimeout,得到一個計算器編號,然后把編號比它小的計數(shù)器全部取消

4.實例:debounce 函數(shù)
debounce(防抖動)監(jiān)聽時間時(Keypress,一直觸發(fā)函數(shù)。
有時,我們不希望回調(diào)函數(shù)被頻繁調(diào)用。比如,用戶填入網(wǎng)頁輸入框的內(nèi)容,希望通過 Ajax 方法傳回服務(wù)器,jQuery 的寫法如下。

$("textarea").on("keydown", ajaxAction);

$("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毫秒之內(nèi),用戶再次擊鍵,就會取消上一次的定時器,然后再新建一個定時器。這樣就保證了回調(diào)函數(shù)之間的調(diào)用間隔,至少是2500毫秒。

5.運(yùn)行機(jī)制
將指定的代碼移到下一輪事件循環(huán),等這輪輪完,再檢查是否到了指定時間。如果到了,就執(zhí)行對應(yīng)的代碼;如果不到,就繼續(xù)等待。

回調(diào)函數(shù)必須等本輪運(yùn)行完,因此時間不確定。

setTimeout(someTask, 100);
veryLongTask();
上面代碼的setTimeout,指定100毫秒以后運(yùn)行一個任務(wù)。但是,如果后面的veryLongTask函數(shù)(同步任務(wù))運(yùn)行時間非常長,過了100毫秒還無法結(jié)束,那么被推遲運(yùn)行的someTask就只有等著,等到veryLongTask運(yùn)行結(jié)束,才輪到它執(zhí)行

6.setTimeout(f, 0)

6.1含義
因為上一節(jié)說過,必須要等到當(dāng)前腳本的同步任務(wù),全部處理完以后,才會執(zhí)行setTimeout指定的回調(diào)函數(shù)f

setTimeout(function () {
console.log(1);
}, 0);
console.log(2);
// 2
// 1
上面代碼先輸出2,再輸出1。因為2是同步任務(wù),在本輪事件循環(huán)執(zhí)行,而1是下一輪事件循環(huán)執(zhí)行。
setTimeout(f, 0)會在下一輪事件循環(huán)一開始就執(zhí)行
6.2應(yīng)用
6.2.1它的一大應(yīng)用是,可以調(diào)整事件的發(fā)生順序。
比如,網(wǎng)頁開發(fā)中,某個事件先發(fā)生在子元素,然后冒泡到父元素,即子元素的事件回調(diào)函數(shù),會早于父元素的事件回調(diào)函數(shù)觸發(fā)。如果,想讓父元素的事件回調(diào)函數(shù)先發(fā)生,就要用到setTimeout(f, 0)。
// HTML 代碼如下
//

var input = document.getElementById("myButton");

input.onclick = function A() {
setTimeout(function B() {

input.value +=" input";

}, 0)
};

document.body.onclick = function C() {
input.value += " body"
};
上面代碼在點(diǎn)擊按鈕后,先觸發(fā)回調(diào)函數(shù)A,然后觸發(fā)函數(shù)C。函數(shù)A中,setTimeout將函數(shù)B推遲到下一輪事件循環(huán)執(zhí)行,這樣就起到了,先觸發(fā)父元素的回調(diào)函數(shù)C的目的了。

6.2.2另一個應(yīng)用是,用戶自定義的回調(diào)函數(shù),通常在瀏覽器的默認(rèn)動作之前觸發(fā)。

比如,用戶在輸入框輸入文本,keypress事件會在瀏覽器接收文本之前觸發(fā)。因此,下面的回調(diào)函數(shù)是達(dá)不到目的的。

// HTML 代碼如下
//

document.getElementById("input-box").onkeypress = function (event) {
this.value = this.value.toUpperCase();
}
上面代碼想在用戶每次輸入文本后,立即將字符轉(zhuǎn)為大寫。但是實際上,它只能將本次輸入前的字符轉(zhuǎn)為大寫,因為瀏覽器此時還沒接收到新的文本,所以this.value取不到最新輸入的那個字符。只有用setTimeout改寫,上面的代碼才能發(fā)揮作用。

document.getElementById("input-box").onkeypress = function() {
var self = this;
setTimeout(function() {

self.value = self.value.toUpperCase();

}, 0);
}
上面代碼將代碼放入setTimeout之中,就能使得它在瀏覽器接收到文本之后觸發(fā)

由于setTimeout(f, 0)實際上意味著,將任務(wù)放到瀏覽器最早可得的空閑時段執(zhí)行,所以那些計算量大、耗時長的任務(wù),常常會被放到幾個小部分,分別放到setTimeout(f, 0)里面執(zhí)行。

var div = document.getElementsByTagName("div")[0];

// 寫法一
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);
上面代碼有兩種寫法,都是改變一個網(wǎng)頁元素的背景色。寫法一會造成瀏覽器“堵塞”,因為 JavaScript 執(zhí)行速度遠(yuǎn)高于 DOM,會造成大量 DOM 操作“堆積”,而寫法二就不會,這就是setTimeout(f, 0)的好處。

6.2.3另一個使用這種技巧的例子是代碼高亮的處理
如果代碼塊很大,一次性處理,可能會對性能造成很大的壓力,那么將其分成一個個小塊,一次處理一塊,比如寫成setTimeout(highlightNext, 50)的樣子,性能壓力就會減輕

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/105806.html

相關(guān)文章

  • 總結(jié)javascript基礎(chǔ)概念():事件隊列循環(huán)

    摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務(wù)隊列掛在當(dāng)前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計時不準(zhǔn)確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點(diǎn)?有什么解決方...

    zhkai 評論0 收藏0
  • javascript基礎(chǔ)總結(jié)()——異步編程情況

    摘要:異步規(guī)定要做一件事,不是立馬執(zhí)行這件事,需要等一定的時間,這樣的話,我們不會等著它執(zhí)行,而是繼續(xù)執(zhí)行下面的操作,只有將下面的事情處理完了,才會返回頭處理之前的事情如果下面的事情并沒有處理完成,不管之前的事情有沒有到時間,都踏踏實實的給我等著 異步:規(guī)定要做一件事,不是立馬執(zhí)行這件事,需要等一定的時間,這樣的話,我們不會等著它執(zhí)行,而是繼續(xù)執(zhí)行下面的操作,只有將下面的事情處理完了,才會返...

    Dionysus_go 評論0 收藏0
  • 異步操作時器

    摘要:提供定時執(zhí)行代碼的功能,叫做定時器,主要由和這兩個函數(shù)來完成。,利用這一點(diǎn),可以寫一個函數(shù),取消當(dāng)前所有的定時器。回調(diào)函數(shù)必須等本輪運(yùn)行完,因此時間不確定。另一個應(yīng)用是,用戶自定義的回調(diào)函數(shù),通常在瀏覽器的默認(rèn)動作之前觸發(fā)。 JavaScript 提供定時執(zhí)行代碼的功能,叫做定時器(timer),主要由setTimeout()和setInterval()這兩個函數(shù)來完成。它們向任務(wù)隊列...

    xcc3641 評論0 收藏0
  • swoole——從入門到放棄(

    摘要:從入門到放棄二一異步毫秒定時器設(shè)置一個間隔時鐘定時器,與定時器不同的是定時器會持續(xù)觸發(fā),直到調(diào)用清除。是一次性函數(shù),執(zhí)行完成后就會銷毀最大不超過使用定時器來刪除定時器。 swoole——從入門到放棄(二) 一、異步毫秒定時器 swoole_timer_tick:設(shè)置一個間隔時鐘定時器,與after定時器不同的是tick定時器會持續(xù)觸發(fā),直到調(diào)用swoole_timer_clear清...

    awokezhou 評論0 收藏0

發(fā)表評論

0條評論

ctriptech

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<