0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡(jiǎn)述javascript定時(shí)器工作原理

jf_78858299 ? 來(lái)源:全棧開(kāi)發(fā)者中心 ? 作者:全棧開(kāi)發(fā)者中心 ? 2023-04-21 14:32 ? 次閱讀

說(shuō)到 javascript 中的定時(shí)器,我們肯定會(huì)想到 setTimeout() 和 setInterval() 這兩個(gè)函數(shù)。本文將從事件循環(huán)(Event Loop) 的角度來(lái)分析兩者的工作原理和區(qū)別。

**setTimeout()**

MDN對(duì) setTimeout 的定義為:

在指定的延遲時(shí)間之后調(diào)用一個(gè)函數(shù)或執(zhí)行一個(gè)代碼片段。

語(yǔ)法

setTimeout 的語(yǔ)法非常簡(jiǎn)單,第一個(gè)參數(shù)為回調(diào)函數(shù),第二個(gè)參數(shù)為延時(shí)的時(shí)間。函數(shù)返回一個(gè)數(shù)值類(lèi)型的ID唯一標(biāo)示符,此ID可以用作 clearTimeout 的參數(shù)來(lái)取消定時(shí)器:

var timeoutID = window.setTimeout(code, delay);

IE0+ 還支持回調(diào)參數(shù)的傳入:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

setInterval()

MDN 對(duì) setInterval 的定義為:

周期性地調(diào)用一個(gè)函數(shù)(function)或者執(zhí)行一段代碼。

由于 setInterval 和 setTimeout 的用法一樣,所以這里不再列出。

對(duì)第二個(gè)參數(shù)(delay)的說(shuō)明

由于javascript 的事件循環(huán)機(jī)制,導(dǎo)致第二個(gè)參數(shù)并不代表延遲delay毫秒之后立即執(zhí)行回調(diào)函數(shù),而是嘗試將回調(diào)函數(shù)加入到事件隊(duì)列。實(shí)際上,setTimeout 和 setInterval 在這一點(diǎn)上處理又存在區(qū)別:

  • setTimeout:延時(shí)delay毫秒之后,啥也不管,直接將回調(diào)函數(shù)加入事件隊(duì)列。
  • setInterval: 延時(shí)delay毫秒之后,先看看事件隊(duì)列中是否存在還沒(méi)有執(zhí)行的回調(diào)函數(shù)(setInterval的回調(diào)函數(shù)),如果存在,就不要再往事件隊(duì)列里加入回調(diào)函數(shù)了。

所以,當(dāng)我們的代碼中存在耗時(shí)的任務(wù)時(shí),定時(shí)器并不會(huì)表現(xiàn)的如我們所想的那樣。

通過(guò)一個(gè)例子來(lái)理解

下面的代碼,本來(lái)希望能夠在 100ms 和 200ms 的時(shí)候(也就是剛好等待 100ms)調(diào)用回調(diào)函數(shù):

var timerStart1 = now();
setTimeout(function () {
  console.log('第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間:', now() - timerStart1);

  var timerStart2 = now();
  setTimeout(function () {
    console.log('第二個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間:', now() - timerStart2);
  }, 100);
}, 100);
// 輸出:
// 第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間: 106
// 第二個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間: 107

這樣的結(jié)果看上去正是我們所想的那樣,但是一旦我們?cè)诖a中加入了耗時(shí)的任務(wù)時(shí)候,結(jié)果就不像我們所期望的那樣了:

var timerStart1 = now();
setTimeout(function () {
  console.log('第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間:', now() - timerStart1);

  var timerStart2 = now();
  setTimeout(function () {
    console.log('第二個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間:', now() - timerStart2);
  }, 100);

  heavyTask();  // 耗時(shí)任務(wù)
}, 100);

var loopStart = now();
heavyTask(); // 耗時(shí)任務(wù)
console.log('heavyTask耗費(fèi)時(shí)間:', now() - loopStart);

function heavyTask() {
  var s = now();
  while(now() - s < 1000) {
  }
}

function now () {
  return new Date();
}
// 輸出:
// heavyTask耗費(fèi)時(shí)間: 1015
// 第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間: 1018
// 第二個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間: 1000

兩個(gè) setTimeout 的等待事件由于耗時(shí)任務(wù)的存在不再是 100ms 了!我們來(lái)描述一下事情的經(jīng)過(guò):

  1. 首先,第一個(gè)耗時(shí)任務(wù)(heavyTask())開(kāi)始執(zhí)行,它需要大約 1000ms 才能執(zhí)行完畢。
  2. 從耗時(shí)任務(wù)開(kāi)始執(zhí)行,過(guò)了 100ms, 第一個(gè) setTimeout 的回調(diào)函數(shù)期望執(zhí)行,于是被加入到事件隊(duì)列,但是此時(shí)前面的耗時(shí)任務(wù)還沒(méi)執(zhí)行完,所以它只能在隊(duì)列中等待,直到耗時(shí)任務(wù)執(zhí)行完畢它才開(kāi)始執(zhí)行,所以結(jié)果中我們開(kāi)的看到的是: 第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間:1018。
  3. 第一個(gè) setTimeout 回調(diào)一執(zhí)行,又開(kāi)啟了第二個(gè) setTimeout, 這個(gè)定時(shí)器也是期望延時(shí) 100ms 之后能夠執(zhí)行它的回調(diào)函數(shù)。但是,在第一個(gè) setTimeout 又存在一個(gè)耗時(shí)任務(wù),所有它的劇情跟第一個(gè)定時(shí)器一樣,也等待了 1000ms 才開(kāi)始執(zhí)行。

可以用下面的圖來(lái)概括:

圖片

再來(lái)看 setInterval 的一個(gè)例子:

var intervalStart = now();
setInterval(function () {
  console.log('interval距定義定時(shí)器的時(shí)間:', now() - loopStart);
}, 100);

var loopStart = now();
heavyTask();
console.log('heavyTask耗費(fèi)時(shí)間:', now() - loopStart);

function heavyTask() {
  var s = now();
  while(now() - s < 1000) {
  }
}

function now () {
  return new Date();
}
// 輸出:
// heavyTask耗費(fèi)時(shí)間: 1013
// interval距定義定時(shí)器的時(shí)間: 1016
// interval距定義定時(shí)器的時(shí)間: 1123
// interval距定義定時(shí)器的時(shí)間: 1224

上面這段代碼,我們期望每隔 100ms 就打出一條日志。相對(duì)于 setTimeout 的區(qū)別, setInterval 在準(zhǔn)備把回調(diào)函數(shù)加入到事件隊(duì)列的時(shí)候,會(huì)判斷隊(duì)列中是否還有未執(zhí)行的回調(diào),如果有的話,它就不會(huì)再往隊(duì)列中添加回調(diào)函數(shù)。 不然,會(huì)出現(xiàn)多個(gè)回調(diào)同時(shí)執(zhí)行的情況。

可以用下面的圖來(lái)概括:

圖片

總結(jié)

上面對(duì)javascript定時(shí)器執(zhí)行原理進(jìn)行了簡(jiǎn)要的分析,希望能夠幫助我們更深入的理解javascript。文中有描述不當(dāng)?shù)牡胤娇梢栽谠u(píng)論中指出。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3218

    瀏覽量

    113665
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4234

    瀏覽量

    61961
  • javascript
    +關(guān)注

    關(guān)注

    0

    文章

    515

    瀏覽量

    53656
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    定時(shí)器的基本工作原理

    一、定時(shí)器的基本概述通過(guò)滴漏和漏沙瓶這兩個(gè)例子簡(jiǎn)單講述定時(shí)器的基本工作原理。STM32的常見(jiàn)的定時(shí)器資源:系統(tǒng)嘀嗒定時(shí)器SysTick、看門(mén)
    發(fā)表于 08-02 08:45

    STM32定時(shí)器工作原理及分類(lèi)

    STM32—定時(shí)器知多少這里寫(xiě)目錄標(biāo)題STM32---定時(shí)器知多少定時(shí)器的分類(lèi)定時(shí)器工作原理定時(shí)器的應(yīng)用
    發(fā)表于 08-02 09:36

    定時(shí)器工作原理

    標(biāo)準(zhǔn)庫(kù)3.5實(shí)現(xiàn):《嵌入式-STM32開(kāi)發(fā)指南》第二部分 基礎(chǔ)篇 - 第4章 定時(shí)器4.1定時(shí)器工作原理STM32有三類(lèi)定時(shí)器,基本定時(shí)器
    發(fā)表于 08-19 07:49

    555定時(shí)器內(nèi)部框圖及電路工作原理

     本文介紹555定時(shí)器內(nèi)部框圖及電路工作原理: 555定時(shí)器內(nèi)部框圖 555集成時(shí)基電路稱(chēng)為集成定時(shí)
    發(fā)表于 11-22 13:00 ?7.8w次閱讀
    555<b class='flag-5'>定時(shí)器</b>內(nèi)部框圖及電路<b class='flag-5'>工作原理</b>

    定時(shí)器/計(jì)數(shù)的結(jié)構(gòu)和工作原理

    定時(shí)器/計(jì)數(shù)的結(jié)構(gòu)和工作原理 定時(shí)器/計(jì)數(shù)的結(jié)構(gòu)  定時(shí)器/計(jì)數(shù)
    發(fā)表于 03-29 09:08 ?1.9w次閱讀
    <b class='flag-5'>定時(shí)器</b>/計(jì)數(shù)<b class='flag-5'>器</b>的結(jié)構(gòu)和<b class='flag-5'>工作原理</b>

    555定時(shí)器工作原理及應(yīng)用引腳圖

    介紹555定時(shí)器工作原理及應(yīng)用引腳圖. 和了解最基本電路
    發(fā)表于 12-23 11:16 ?16次下載

    單片機(jī)計(jì)數(shù)_定時(shí)器工作原理_

    單片機(jī)計(jì)數(shù)_定時(shí)器工作原理,定時(shí)器、計(jì)數(shù)寄存,以及定時(shí)
    發(fā)表于 05-06 14:12 ?1次下載

    SysTick定時(shí)器工作原理介紹

    今天給大家介紹一下 STM32F103 單片機(jī)的 SysTick 定時(shí)器工作原理,在給大家講解新課之前,看一個(gè)我們以前寫(xiě)的一個(gè)延時(shí)函數(shù)。
    發(fā)表于 11-11 17:17 ?22次下載

    51單片機(jī)定時(shí)器工作原理

    51單片機(jī)定時(shí)器工作原理及用法
    的頭像 發(fā)表于 03-14 13:51 ?9.4w次閱讀

    小風(fēng)扇定時(shí)器電路圖及工作原理

    本文主要介紹了小風(fēng)扇定時(shí)器電路圖及工作原理說(shuō)明。
    發(fā)表于 10-25 15:05 ?2.2w次閱讀
    小風(fēng)扇<b class='flag-5'>定時(shí)器</b>電路圖及<b class='flag-5'>工作原理</b>

    簡(jiǎn)述555定時(shí)器設(shè)計(jì)數(shù)字時(shí)鐘

    簡(jiǎn)述555定時(shí)器設(shè)計(jì)數(shù)字時(shí)鐘
    發(fā)表于 10-08 16:26 ?22次下載

    定時(shí)器中斷是什么意思,定時(shí)器中斷的工作原理

    定時(shí)器中斷是由單片機(jī)中的定時(shí)器溢出而申請(qǐng)的中斷。51單片機(jī)中有兩個(gè)定時(shí)器T0和T1。STM32中共有11個(gè)定時(shí)器
    的頭像 發(fā)表于 07-23 09:45 ?5635次閱讀

    555定時(shí)器的三種典型應(yīng)用 簡(jiǎn)述555定時(shí)器工作原理

    555定時(shí)器是一種廣泛使用的集成電路,在電子電路中有許多常見(jiàn)的應(yīng)用。以下是555定時(shí)器的三種典型應(yīng)用
    發(fā)表于 07-28 10:12 ?5502次閱讀

    PLC定時(shí)器工作原理和應(yīng)用

    至關(guān)重要的角色。定時(shí)器能夠?qū)崿F(xiàn)對(duì)時(shí)間的精確控制,是控制系統(tǒng)中實(shí)現(xiàn)延時(shí)、定時(shí)、周期控制等功能的關(guān)鍵元件之一。本文將詳細(xì)闡述PLC中定時(shí)器工作原理及應(yīng)用,以期為相關(guān)技術(shù)人員提供參考。
    的頭像 發(fā)表于 06-18 11:55 ?1187次閱讀

    簡(jiǎn)述單片機(jī)定時(shí)器工作原理

    單片機(jī)定時(shí)器工作原理是一個(gè)復(fù)雜而精細(xì)的過(guò)程,它涉及到單片機(jī)內(nèi)部的多個(gè)組件和機(jī)制。
    的頭像 發(fā)表于 08-19 18:20 ?579次閱讀