JS定時(shí)器

前言:對定時(shí)器的小整理。

JS單線程

  • Javascript語言的執(zhí)行環(huán)境是"單線程"(single thread)。也就是說,瀏覽器只分配給js一個(gè)主線程用來執(zhí)行任務(wù)即函數(shù),但是每次只能執(zhí)行一個(gè)任務(wù),只有等到當(dāng)前任務(wù)執(zhí)行完成后,才執(zhí)行后面的任務(wù),這些任務(wù)形成一個(gè)任務(wù)隊(duì)列排隊(duì)等候執(zhí)行

  • 為了避免因?yàn)槟承╅L時(shí)間任務(wù)造成的無意義等待,JS引入了異步的概念,用另一個(gè)線程來管理異步任務(wù)。

  • 同步任務(wù)直接在主線程隊(duì)列中順序執(zhí)行,而異步任務(wù)會(huì)進(jìn)入另一個(gè)任務(wù)隊(duì)列,不會(huì)阻塞主線程。等到主線程隊(duì)列空了(執(zhí)行完了)的時(shí)候,就會(huì)去異步隊(duì)列查詢是否有可執(zhí)行的異步任務(wù)了(異步任務(wù)通常進(jìn)入異步隊(duì)列之后還要等一些條件才能執(zhí)行,如ajax請求、文件讀寫),如果某個(gè)異步任務(wù)可以執(zhí)行了便加入主線程隊(duì)列,以此循環(huán)。

JS定時(shí)器

定時(shí)器也是一種異步任務(wù),通常瀏覽器都有一個(gè)獨(dú)立的定時(shí)器模塊,定時(shí)器的延遲時(shí)間就由定時(shí)器模塊來管理,當(dāng)某個(gè)定時(shí)器到了可執(zhí)行狀態(tài),就會(huì)被加入主線程隊(duì)列。

基本計(jì)時(shí)器

  • setInterval() :以指定時(shí)間為周期循環(huán)執(zhí)行
  • setTimeout(): 只在指定時(shí)間后執(zhí)行一次

寫法

  • setInterval(expression,milliseconds)
  • setTimeout(expression,milliseconds)
  • 其中expression既可以是字符串,也可以是匿名函數(shù),或者是一個(gè)函數(shù)名,milliseconds是延時(shí)或者重復(fù)執(zhí)行的毫秒數(shù)

例子

setTimeout(function () {
    console.log('timeout');
}, 1000);

setInterval(function () {
    console.log('interval')
}, 1000);

// 輸出一次 timeout,每隔1S輸出一次 interval

清除定時(shí)器

  • 定時(shí)器清除的方法:clearInterval(str)和clearTimeout(str)
  • 定時(shí)器有個(gè)返回值,該數(shù)字代表定時(shí)器的序號,即第多少個(gè)定時(shí)器,我們獲取其返回值后,調(diào)用clearInterval(返回值)或clearTimeout(返回值), 即可停止計(jì)時(shí)器
  • 要清除定時(shí)器,就必須在用定時(shí)器的時(shí)候,定義一個(gè)變量來記錄定時(shí)器的返回值

定時(shí)器的返回值:

 var timer1=window.setTimeout(function(){
            console.log("我是第一個(gè)定時(shí)器")
        },1000);
        console.log(timer1);//1
var timer2=window.setTimeout(function(){
            console.log("我是第二個(gè)定時(shí)器")
        },1000);
        console.log(timer2);//2

清除定時(shí)器:


var id=window.setInterval("somefunction",10000); 
//取消定時(shí)執(zhí)行 
window.clearInterval(id); 
id=null;

注意:

  1. setTimeout雖然只執(zhí)行一次,但執(zhí)行后,定時(shí)器還在,只是沒用了而已
  2. 定時(shí)器即使清除了,其返回值也不會(huì)清除,之后設(shè)置的定時(shí)器的返回值也會(huì)在其返回值的基礎(chǔ)上繼續(xù)向后排
  3. 一般清空定時(shí)器后會(huì)將清空的定時(shí)器的變量置空,這樣寫既可以釋放內(nèi)存,也可以便于后邊代碼的判斷。

定時(shí)器傳遞參數(shù)

先看一下定時(shí)器的常用寫法:

  1. 函數(shù)名,不帶參數(shù)
    setInterval(test,1000); //1秒后執(zhí)行
  2. 字符串,可以執(zhí)行的代碼
    setInterval('test()',1000); //1秒后執(zhí)行
  3. 匿名函數(shù)
    setInterval(function(){},1000); //1秒后執(zhí)行
  4. 調(diào)用函數(shù)
    setInterval(test(),1000); //立即執(zhí)行

在使用函數(shù)名作為調(diào)用句柄時(shí)都不能帶參數(shù),而在許多場合必須要帶參數(shù)

函數(shù)hello

var userName="jack";
//根據(jù)用戶名顯示歡迎信息
function hello(_name){
      alert("hello,"+_name);
}
window.setTimeout(hello(userName),3000);//會(huì)立即執(zhí)行,不是等3秒后執(zhí)行

修改:

window.setTimeout("hello(userName)",3000);

注:其他方法見

異步之定時(shí)器

setTimeout為例:

setTimeout(function(){
  console.log(0);
},0)
 
console.log(1);
 
// 1
 
// 0
  • 大家可能疑問了,setTimeout中設(shè)置的推遲執(zhí)行的毫秒數(shù)是0呀,不就是立即執(zhí)行的意思嗎。實(shí)際在執(zhí)行程序的時(shí)候,瀏覽器會(huì)默認(rèn)setTimeout以及ajax請求這一類的方法都是耗時(shí)程序(盡管可能不耗時(shí)),所以此時(shí)的setTimeout盡管它推遲時(shí)間為0,但是js不會(huì)立即執(zhí)行,而是把它加入任務(wù)隊(duì)列,當(dāng)執(zhí)行完執(zhí)行棧的同步任務(wù)也就是打印1后,再執(zhí)行setTimeout的回調(diào)函數(shù),打印0。
  • 總之,setTimeout(fn,0)的含義是,指定某個(gè)任務(wù)在主線程最早可得的空閑時(shí)間執(zhí)行,也就是說,盡可能早得執(zhí)行。它在"任務(wù)隊(duì)列"的尾部添加一個(gè)事件,因此要等到同步任務(wù)和"任務(wù)隊(duì)列"現(xiàn)有的事件都處理完,才會(huì)得到執(zhí)行。
  • 所以注意的是,setTimeout()只是將事件插入了任務(wù)隊(duì)列,必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,主線程才會(huì)去執(zhí)行它指定的回調(diào)函數(shù)。但如果當(dāng)前任務(wù)十分耗時(shí),需要等很久,所以并沒有辦法保證,回調(diào)函數(shù)一定會(huì)在setTimeout()指定的時(shí)間執(zhí)行,比如說你指定10ms后執(zhí)行,但是當(dāng)前的任務(wù)執(zhí)行了20ms,所以setTimeout的回調(diào)函數(shù)并不能在10ms后立即執(zhí)行,可能要20ms后,如果setTimeout在任務(wù)隊(duì)列中不是排第一位,可能還不止20ms。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、 單線程、任務(wù)隊(duì)列的概念 單線程: JavaScript是一個(gè)單線程語言,瀏覽器只會(huì)分配一個(gè)javascrip...
    海山城閱讀 1,109評論 0 1
  • 從JS執(zhí)行機(jī)制說起 瀏覽器(或者說JS引擎)執(zhí)行JS的機(jī)制是基于事件循環(huán)。 由于JS是單線程,所以同一時(shí)間只能執(zhí)行...
    love2013閱讀 953評論 0 1
  • 在談js定時(shí)器以前,我覺得有必要了解下javascript的事件運(yùn)行機(jī)制,簡稱(javascript event ...
    JohnsonChe閱讀 1,019評論 0 2
  • 定時(shí)器 JavaScript提供定時(shí)執(zhí)行代碼的功能,叫做定時(shí)器(timer),主要由setTimeout()和se...
    李諾哦閱讀 1,087評論 0 0
  • 你:親愛的,我發(fā)現(xiàn)你有一種魔力,能讓我一直想著你、盯著你 我:你又何嘗不是!??!
    你叫我婆婆閱讀 103評論 0 0

友情鏈接更多精彩內(nèi)容