JS定時器機制詳解

前言

JavaScript 提供定時執行代碼的功能,叫作定時器(timer),主要由setTimeout()setInterval()這兩個函數來完成。它們向任務隊列添加定時任務。在瞭解定時器前,你首頁也要對事件循環機制有必定的瞭解。能夠先閱讀這篇文章Js事件循環(Event Loop)機制git

更多優質文章請猛戳GitHub博客,歡迎帥哥美女前來Star!!!github

基本概念

什麼是定時器?

定時器是一種異步任務,一般瀏覽器都有一個獨立的定時器模塊,定時器的延遲時間就由定時器模塊來管理,當某個定時器到了可執行狀態,就會被加入主線程隊列。瀏覽器

定時器的運行機制是什麼?

定時器的運行機制,是將指定的代碼移出本輪事件循環,等到下一輪事件循環,再檢查是否到了指定時間。若是到了,就執行對應的代碼;若是不到,就繼續等待。bash

定時器解決了什麼問題?

因爲JS的單線程特性,定時器提供了一種跳出單線程限制的方法,即讓一段代碼在必定毫秒以後,再異步執行。異步

基本用法

setTimeout()

setTimeout函數用來指定某個函數或某段代碼,在多少毫秒以後執行。它返回一個整數,表示定時器的編號,之後能夠用來取消這個定時器。函數

var timer = setTimeout(func|code, delay);

clearTimeout(timer);
複製代碼

setTimeout接受兩個參數:oop

  • func|code: 是將要推遲執行的函數名或者一段代碼。
  • delay: 是推遲執行的毫秒數。
  • clearTimeout(): 是取消對應的定時器的函數。

除了前兩個參數,setTimeout還容許更多的參數。它們將依次傳入推遲執行的函數(回調函數)。post

舉個栗子:ui

setTimeout(function (a,b) {
  console.log(a + b);
}, 1000, 1, 1);
複製代碼

setInterval()

setInterval函數的用法與setTimeout徹底一致,區別僅僅在於setInterval指定某個任務每隔一段時間就執行一次,也就是無限次的定時執行。spa

var timer = setInterval(function() {
  console.log(2);
}, 1000)

clearInterval(timer)
複製代碼

上面代碼中,每隔1000毫秒就輸出一個2,會無限運行下去,直到關閉當前窗口。clearInterval函數是用來取消對應的定時器的。其餘的跟setTimeout基本同樣。

深刻機制

定時器不是JavaScript的一項功能,而是做爲對象和方法的一部分,在瀏覽器中使用。也就是說,在非瀏覽器環境中使用JavaScript,極可能定時器不存在來。

咱們都知道JavaScript是單線程的,這也決定了在異步事件(鼠標單擊、定時器等)程序的處理中,在線程中沒有代碼的時候纔會執行。即處理程序須要排隊執行,且不會被其餘處理程序中斷。

下面經過例子來了解定時器的詳細機制:

  • 0ms時,處啓動一個10ms延遲的定時器,以及一個10ms間隔定時器。
  • 6ms時,觸發鼠標點擊事件。
  • 10ms時,定時器和第一個間隔定時器都過時了(因爲主程序還在執行,因此定時器仍然在排隊,等待空閒在執行)。
  • 因爲定時器和點擊事件都是異步事件,因此他們會進行事件排隊,當主程序的同步事件執行完成(即在18ms以後),線程空閒時才執行。
  • 18ms時,主線程執行完畢,開始執行隊列裏面的事件,隊列裏面如今有鼠標單擊事件、setTimeout定時器和setInterval定時器。
  • 20ms時,因爲隊列裏面有setInterval定時器,因此第二個到期的間隔定時器就會做廢處理。
  • 28ms時,單擊事件執行完成,而且在10ms就應該執行的setTimeout定時器,如今纔開始執行。
  • 30ms時,第三個setInterval定時器到期,因隊列中有間隔定時器,因此第三個也做廢。
  • 34ms時,setTimeout定時器執行完成,開始執行setInterval,但因爲第一個間隔定時器在42ms時結束,因此40ms時,到期的第二個間隔定時器,又要進行排隊等待。
  • 47ms時,因爲第二個setInterval能夠在第三個間隔定時器50ms到期時執行完,因此不須要排隊直接執行。

根據上面的流程進行小結:

  • 事件排隊:同時發生了這麼多事情,因爲js的單線程特性,當線程正在執行狀態,有異步事件觸發時,它就會排隊,而且在線程空閒時才進行執行。而且依照先進先出的順序執行(先排隊的先執行)。
  • setInterval調用被廢棄:在線程被佔用的狀況下,而且隊列中已經有setInterval在排隊,則下一個到期的setInterval會被廢棄。
  • 定時器沒法保證準時執行回調函數:在主線程尚未結束,即便定時器時間到期仍然不會執行,必須等到主程序同步代碼所有執行完。
  • setTimeout和setInterval的區別:其最主要的區別是功能上的區別,setTimeout只延遲執行一次,setInterval按時間週期性的執行。

其餘相關知識:

  • 定時器不能很是細粒化的控制執行的時間,建議在15ms以上。
  • 可使用定時器來分解長時間運行的任務,

結語

即便設置了時間,若是使用不當的話,定時器仍是不會保證準時執行回調函數。而經過本文,相信你之前對定時器出現過相似問題有了必定的瞭解。但願你們熟練理解原理,你們加油!!

相關文章
相關標籤/搜索