肉动漫无修3D在线观看-肉动漫无码无删减在线观看-肉动漫h黄动漫日本免费观看-肉动漫3D卡通无修在线播放-床上色APP下载免费版-床伴在线观看免费高清完整泰剧第四集

Web前端知識(shí)

首頁 > 免費(fèi) > Web前端知識(shí) >

JavaScript定時(shí)器與執(zhí)行機(jī)制解析

來源:北京匯仁智杰科技有限公司   時(shí)間:2016-05-25   點(diǎn)擊:

  從JS執(zhí)行機(jī)制說起
  瀏覽器(或者說JS引擎)執(zhí)行JS的機(jī)制是基于事件循環(huán)。
  由于JS是單線程,所以同一時(shí)間只能執(zhí)行一個(gè)任務(wù),其他任務(wù)就得排隊(duì),后續(xù)任務(wù)必須等到前一個(gè)任務(wù)結(jié)束才能開始執(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í)器
  JS的定時(shí)器目前有三個(gè):setTimeout、setInterval和setImmediate。
  定時(shí)器也是一種異步任務(wù),通常瀏覽器都有一個(gè)獨(dú)立的定時(shí)器模塊,定時(shí)器的延遲時(shí)間就由定時(shí)器模塊來管理,當(dāng)某個(gè)定時(shí)器到了可執(zhí)行狀態(tài),就會(huì)被加入主線程隊(duì)列。
   JS定時(shí)器非常實(shí)用,做動(dòng)畫的肯定都用到過,也是最常用的異步模型之一。
  有時(shí)候一些奇奇怪怪的問題,加一個(gè)setTimeout(fn, 0)(以下簡寫setTimeout(0))就解決了。不過,如果對定時(shí)器本身不熟悉,也會(huì)產(chǎn)生一些奇奇怪怪的問題。
  setTimeout
  setTimeout(fn, x)表示延遲x毫秒之后執(zhí)行fn。
  使用的時(shí)候千萬不要太相信預(yù)期,延遲的時(shí)間嚴(yán)格來說總是大于x毫秒的,至于大多少就要看當(dāng)時(shí)JS的執(zhí)行情況了。
  另外,多個(gè)定時(shí)器如不及時(shí)清除(clearTimeout),會(huì)存在干擾,使延遲時(shí)間更加捉摸不透。所以,不管定時(shí)器有沒有執(zhí)行完,及時(shí)清除已經(jīng)不需要的定時(shí)器是個(gè)好習(xí)慣。
  HTML5規(guī)范規(guī)定最小延遲時(shí)間不能小于4ms,即x如果小于4,會(huì)被當(dāng)做4來處理。 不過不同瀏覽器的實(shí)現(xiàn)不一樣,比如,Chrome可以設(shè)置1ms,IE11/Edge是4ms。
  setTimeout注冊的函數(shù)fn會(huì)交給瀏覽器的定時(shí)器模塊來管理,延遲時(shí)間到了就將fn加入主進(jìn)程執(zhí)行隊(duì)列,如果隊(duì)列前面還有沒有執(zhí)行完的代碼,則又需要花一點(diǎn)時(shí)間等待才能執(zhí)行到fn,所以實(shí)際的延遲時(shí)間會(huì)比設(shè)置的長。如在fn之前正好有一個(gè)超級(jí)大循環(huán),那延遲時(shí)間就不是一丁點(diǎn)了。
  (function testSetTimeout() {
  const label = 'setTimeout';
  console.time(label);
  setTimeout(() => {
   console.timeEnd(label);
  }, 10);
  for(let i = 0; i < 100000000; i++) {}
  })();
  setInterval結(jié)果是:setTimeout: 335.187ms,遠(yuǎn)遠(yuǎn)不止10ms。
  setInterval的實(shí)現(xiàn)機(jī)制跟setTimeout類似,只不過setInterval是重復(fù)執(zhí)行的。
  對于setInterval(fn, 100)容易產(chǎn)生一個(gè)誤區(qū):并不是上一次fn執(zhí)行完了之后再過100ms才開始執(zhí)行下一次fn。 事實(shí)上,setInterval并不管上一次fn的執(zhí)行結(jié)果,而是每隔100ms就將fn放入主線程隊(duì)列,而兩次fn之間具體間隔多久就不一定了,跟setTimeout實(shí)際延遲時(shí)間類似,和JS執(zhí)行情況有關(guān)。
  (function testSetInterval() {
  let i = 0;
  const start = Date.now();
  const timer = setInterval(() => {
  i += 1;
   i === 5  clearInterval(timer);
  console.log(`第${i}次開始`, Date.now() - start);
  for(let i = 0; i < 100000000; i++) {}
  console.log(`第${i}次結(jié)束`, Date.now() - start);
  }, 100);
  })();
  輸出
  第1次開始 100
  第1次結(jié)束 1089
  第2次開始 1091
  第2次結(jié)束 1396
  第3次開始 1396
  第3次結(jié)束 1701
  第4次開始 1701
  第4次結(jié)束 2004
  第5次開始 2004
  第5次結(jié)束 2307
  另外可以看出,當(dāng)setInterval的回調(diào)函數(shù)執(zhí)行時(shí)間超過了延遲時(shí)間,已經(jīng)完全看不出有時(shí)間間隔了。可見,雖然每次fn執(zhí)行時(shí)間都很長,但下一次并不是等上一次執(zhí)行完了再過100ms才開始執(zhí)行的,實(shí)際上早就已經(jīng)等在隊(duì)列里了。
  如果setTimeout和setInterval都在延遲100ms之后執(zhí)行,那么誰先注冊誰就先執(zhí)行回調(diào)函數(shù)。
  setImmediate
  這算一個(gè)比較新的定時(shí)器,目前IE11/Edge支持、Nodejs支持,Chrome不支持,其他瀏覽器未測試。
  從API名字來看很容易聯(lián)想到setTimeout(0),不過setImmediate應(yīng)該算是setTimeout(0)的替代版。
  在IE11/Edge中,setImmediate延遲可以在1ms以內(nèi),而setTimeout有最低4ms的延遲,所以setImmediate比setTimeout(0)更早執(zhí)行回調(diào)函數(shù)。不過在Nodejs中,兩者誰先執(zhí)行都有可能,原因是Nodejs的事件循環(huán)和瀏覽器的略有差異。
  (function testSetImmediate() {
  const label = 'setImmediate';
  console.time(label);
  setImmediate(() => {
  console.timeEnd(label);
  });
  })();
  Edge輸出:setImmediate: 0.555 毫秒
  很明顯,setImmediate設(shè)計(jì)來是為保證讓代碼在下一次事件循環(huán)執(zhí)行,以前setTimeout(0)這種不可靠的方式可以丟掉了。
  其他常用異步模型
  requestAnimationFrame
  requestAnimationFrame并不是定時(shí)器,但和setTimeout很相似,在沒有requestAnimationFrame的瀏覽器一般都是用setTimeout模擬。
  requestAnimationFrame跟屏幕刷新同步,大多數(shù)屏幕的刷新頻率都是60Hz,對應(yīng)的requestAnimationFrame大概每隔16.7ms觸發(fā)一次,如果屏幕刷新頻率更高,requestAnimationFrame也會(huì)更快觸發(fā)。基于這點(diǎn),在支持requestAnimationFrame的瀏覽器還使用setTimeout做動(dòng)畫顯然是不明智的。
  在不支持requestAnimationFrame的瀏覽器,如果使用setTimeout/setInterval來做動(dòng)畫,最佳延遲時(shí)間也是16.7ms。 如果太小,很可能連續(xù)兩次或者多次修改dom才一次屏幕刷新,這樣就會(huì)丟幀,動(dòng)畫就會(huì)卡;如果太大,顯而易見也會(huì)有卡頓的感覺。
  有趣的是,第一次觸發(fā)requestAnimationFrame的時(shí)機(jī)在不同瀏覽器也存在差異,Edge中,大概16.7ms之后觸發(fā),而Chrome則立即觸發(fā),跟setImmediate差不多。按理說Edge的實(shí)現(xiàn)似乎更符合常理。
  (function testRequestAnimationFrame() {
  const label = 'requestAnimationFrame';
  console.time(label);
  requestAnimationFrame(() => {
   console.timeEnd(label);
  });
  })();
  Edge輸出:requestAnimationFrame: 16.66 毫秒
  Chrome輸出:requestAnimationFrame: 0.698ms
  但相鄰兩次requestAnimationFrame的時(shí)間間隔大概都是16.7ms,這一點(diǎn)是一致的。當(dāng)然也不是絕對的,如果頁面本身性能就比較低,相隔的時(shí)間可能會(huì)變大,這就意味著頁面達(dá)不到60fps。
  Promise
  Promise是很常用的一種異步模型,如果我們想讓代碼在下一個(gè)事件循環(huán)執(zhí)行,可以選擇使用setTimeout(0)、setImmediate、requestAnimationFrame(Chrome)和Promise。
  而且Promise的延遲比setImmediate更低,意味著Promise比setImmediate先執(zhí)行。
  function testSetImmediate() {
  const label = 'setImmediate';
  console.time(label);
  setImmediate(() => {
  console.timeEnd(label);
  });
  }
  function testPromise() {
  const label = 'Promise';
  console.time(label);
  new Promise((resolve, reject) => {
  resolve();
  }).then(() => {
  console.timeEnd(label);
  });
  }
  testSetImmediate();
  testPromise();
  Edge輸出:Promise: 0.33 毫秒 setImmediate: 1.66 毫秒
  盡管setImmediate的回調(diào)函數(shù)比Promise先注冊,但還是Promise先執(zhí)行。
  可以肯定的是,在各JS環(huán)境中,Promise都是最先執(zhí)行的,setTimeout(0)、setImmediate和requestAnimationFrame順序不確定。
  process.nextTick
  process.nextTick是Nodejs的API,比Promise更早執(zhí)行。
  事實(shí)上,process.nextTick是不會(huì)進(jìn)入異步隊(duì)列的,而是直接在主線程隊(duì)列尾強(qiáng)插一個(gè)任務(wù),雖然不會(huì)阻塞主線程,但是會(huì)阻塞異步任務(wù)的執(zhí)行,如果有嵌套的process.nextTick,那異步任務(wù)就永遠(yuǎn)沒機(jī)會(huì)被執(zhí)行到了。
  使用的時(shí)候要格外小心,除非你的代碼明確要在本次事件循環(huán)結(jié)束之前執(zhí)行,否則使用setImmediate或者Promise更保險(xiǎn)。

網(wǎng)絡(luò)營銷推廣 . 北京匯仁智杰科技有限公司!

地址:北京市昌平區(qū)回龍觀龍冠大廈5層
咨詢:13370157521
業(yè)務(wù)QQ:373002979
E - mail:sales @ huirenzhijie.com
企業(yè)網(wǎng)站備案:京ICP備15021091號(hào)-1

匯仁智杰與眾不同

  • 有網(wǎng)絡(luò)推廣經(jīng)驗(yàn)
  • 有網(wǎng)站建站隊(duì)伍
  • 有大型網(wǎng)站建設(shè)經(jīng)驗(yàn)
  • 致力于營銷型網(wǎng)站建設(shè)
  • 始終堅(jiān)持技術(shù)和服務(wù)同樣重要
查看PC版網(wǎng)站
備案號(hào):京ICP備15021091號(hào)-1 版權(quán)所有:匯仁智杰

主站蜘蛛池模板: 红番阁免费观看 | 伧理片午夜伧理片 | jizz黑丝 | 亚洲日韩有码无线免费 | 亚洲免费国产在线日韩 | 夫妻性姿势真人做视频 | 老头狠狠挺进小莹体内视频 | 久久香蕉国产线看观看精品 | 精品国产中文字幕在线视频 | 日韩在线看片中文字幕不卡 | 一受多攻高h | 美女张开腿让男人桶爽无弹窗 | japanesematur乱儿| 国产在线亚洲精品观 | 清冷受被CAO的合不拢 | 国产精品综合AV一区二区国产馆 | 中文字幕亚洲乱码熟女在线 | 一进一出抽搐gif免费60秒 | 免费乱理伦片在线观看八戒 | 92国产精品午夜免费福利视频 | 国产一区二区三区内射高清 | 九九热这里只有国产精品 | 桃花免费高清在线观看 | 国产精品色欲AV亚洲三区软件 | 无码日韩人妻精品久久蜜桃免费 | 热久久伊大人香蕉网老师 | A级毛片高清免费网站不卡 a级毛片高清免费视频 | 一本色道久久综合亚洲精品加 | 76人遣返航班上71人呈阳性 | 国产永久免费观看视频软件 | 607080老太太AW| 国产色婷婷精品人妻蜜桃成熟时 | 久久亚洲欧美国产综合 | 久久久久国产一级毛片高清片 | 亚洲午夜无码久久久久蜜臀av | 青青草伊人 | 亚洲91av | 秋霞电影网视频一区二区三区 | 亚洲精品AV无码永久无码 | 午夜伦yy44880影院 | 亚洲国产精品99久久久久久 |