亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

javascript 定時(shí)器工作原理

godlong_X / 2018人閱讀

摘要:說到中的定時(shí)器,我們肯定會(huì)想到和這兩個(gè)函數(shù)。第一個(gè)回調(diào)一執(zhí)行,又開啟了第二個(gè),這個(gè)定時(shí)器也是期望延時(shí)之后能夠執(zhí)行它的回調(diào)函數(shù)??梢杂孟旅娴膱D來概括總結(jié)上面對(duì)定時(shí)器執(zhí)行原理進(jìn)行了簡(jiǎn)要的分析,希望能夠幫助我們更深入的理解。

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

setTimeout()

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

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

語法

setTimeout 的語法非常簡(jiǎn)單,第一個(gè)參數(shù)為回調(diào)函數(shù),第二個(gè)參數(shù)為延時(shí)的時(shí)間。函數(shù)返回一個(gè)數(shù)值類型的ID唯一標(biāo)示符,此ID可以用作 clearTimeout 的參數(shù)來取消定時(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í)行一段代碼。

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

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

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

setTimeout:延時(shí)delay毫秒之后,啥也不管,直接將回調(diào)函數(shù)加入事件隊(duì)列。

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

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

通過一個(gè)例子來理解

下面的代碼,本來希望能夠在 100ms200ms 的時(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 了!我們來描述一下事情的經(jīng)過:

首先,第一個(gè)耗時(shí)任務(wù)(heavyTask())開始執(zhí)行,它需要大約 1000ms 才能執(zhí)行完畢。

從耗時(shí)任務(wù)開始執(zhí)行,過了 100ms, 第一個(gè) setTimeout 的回調(diào)函數(shù)期望執(zhí)行,于是被加入到事件隊(duì)列,但是此時(shí)前面的耗時(shí)任務(wù)還沒執(zhí)行完,所以它只能在隊(duì)列中等待,直到耗時(shí)任務(wù)執(zhí)行完畢它才開始執(zhí)行,所以結(jié)果中我們開的看到的是: 第一個(gè)setTimeout回調(diào)執(zhí)行等待時(shí)間: 1018。

第一個(gè) setTimeout 回調(diào)一執(zhí)行,又開啟了第二個(gè) setTimeout, 這個(gè)定時(shí)器也是期望延時(shí) 100ms 之后能夠執(zhí)行它的回調(diào)函數(shù)。 但是,在第一個(gè) setTimeout 又存在一個(gè)耗時(shí)任務(wù),所有它的劇情跟第一個(gè)定時(shí)器一樣,也等待了 1000ms 才開始執(zhí)行。

可以用下面的圖來概括:

再來看 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í)行的情況。

可以用下面的圖來概括:

總結(jié)

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

文章地址:http://blog.mcbird.cn/2015/09/18/javascript-timers/

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/85989.html

相關(guān)文章

  • JavaScript的計(jì)時(shí)器工作原理

    摘要:創(chuàng)建了一個(gè)簡(jiǎn)單的計(jì)時(shí)器,在經(jīng)過給定的時(shí)間后,回調(diào)函數(shù)將會(huì)被執(zhí)行。接受一個(gè)計(jì)時(shí)器由之前兩種計(jì)時(shí)器返回并且停止計(jì)時(shí)器回調(diào)函數(shù)的執(zhí)行。然而,我們可以注意到,當(dāng)定時(shí)器再一次觸發(fā)在計(jì)時(shí)器回調(diào)函數(shù)正在執(zhí)行的時(shí)候,這一次定時(shí)器回調(diào)函數(shù)被丟棄了。 最近都在看一些JavaScript原理層面的文章,恰巧看到了jQuery的作者的一篇關(guān)于JavaScript計(jì)時(shí)器原理的解析,于是誠(chéng)惶誠(chéng)恐地決定把原文翻譯成...

    geekzhou 評(píng)論0 收藏0
  • Javascript時(shí)器那些事兒

    摘要:一什么是定時(shí)器提供了一些原生方法來實(shí)現(xiàn)延時(shí)去執(zhí)行某一段代碼,下面來簡(jiǎn)單介紹一下設(shè)置一個(gè)定時(shí)器,在定時(shí)器到期后執(zhí)行一次函數(shù)或代碼段定時(shí)器延遲后執(zhí)行的函數(shù)延遲后執(zhí)行的代碼字符串,不推薦使用原理類似延遲的時(shí)間單位毫秒,默認(rèn)值為向延遲函數(shù)傳遞而外的 一、什么是定時(shí)器 JS提供了一些原生方法來實(shí)現(xiàn)延時(shí)去執(zhí)行某一段代碼,下面來簡(jiǎn)單介紹一下 setTimeout: 設(shè)置一個(gè)定時(shí)器,在定時(shí)器到期后執(zhí)行...

    Riddler 評(píng)論0 收藏0
  • JavaScript 工作原理之四-事件循環(huán)及異步編程的出現(xiàn)和 5 種更好的 async/await

    摘要:函數(shù)會(huì)在之后的某個(gè)時(shí)刻觸發(fā)事件定時(shí)器。事件循環(huán)中的這樣一次遍歷被稱為一個(gè)。執(zhí)行完畢并出棧。當(dāng)定時(shí)器過期,宿主環(huán)境會(huì)把回調(diào)函數(shù)添加至事件循環(huán)隊(duì)列中,然后,在未來的某個(gè)取出并執(zhí)行該事件。 原文請(qǐng)查閱這里,略有改動(dòng)。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第四章。 現(xiàn)在,我們將會(huì)通過回顧單線程環(huán)境下編程的弊端及如何克服這些困難以創(chuàng)建令人驚嘆...

    maochunguang 評(píng)論0 收藏0
  • 談?wù)勎覍?duì)js中時(shí)器的一點(diǎn)理解

    摘要:這兩個(gè)函數(shù)接受定時(shí)器的例如我們上面提到的兩個(gè)函數(shù)產(chǎn)生的定時(shí)器,并停止對(duì)定時(shí)器中指定函數(shù)的調(diào)用。注意,定時(shí)器雖然觸發(fā)了,但是并不會(huì)立即執(zhí)行,它只是把需要延遲執(zhí)行的函數(shù)加入了執(zhí)行隊(duì)列,在線程的某一個(gè)可用的時(shí)間點(diǎn),這個(gè)函數(shù)就能夠得到執(zhí)行。 擼了今年阿里、頭條和美團(tuán)的面試,我有一個(gè)重要發(fā)現(xiàn)....... javascript定時(shí)器工作原理是一個(gè)重要的基礎(chǔ)知識(shí)點(diǎn)。因?yàn)槎〞r(shí)器在單線程中工作,它們表...

    frontoldman 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<