日韩欧美人妻无码精品白浆,夜夜嗨AV免费入口,国产欧美官网在线看,高校回应聋哑女生因长相完美被质疑

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

你不知道的setTimeout

liguoquan
2024年12月27日 12:39 本文熱度 1068
:你不知道的setTimeout


你不知道的setTimeout

前言

setTimeout() 我們?cè)谌粘9ぷ髦薪?jīng)常使用,最近做了一個(gè)功能是關(guān)于setTimeout()的,總結(jié)了一些用法。

在這篇文章中,你將了解 setTimeout() 方法——它是什么以及如何在你的程序中使用它。

以下是我在這篇快速指南中要介紹的內(nèi)容:

  • JavaScript 中的  setTimeout() 基本語(yǔ)法
  • 進(jìn)階語(yǔ)法:防抖、代碼邏輯執(zhí)行時(shí)間可能比定時(shí)器時(shí)間間隔要長(zhǎng)如何處理
  • setTimeout()的定時(shí)器是否精準(zhǔn)
  • 定時(shí)器在非激活tab或者熄屏的時(shí)候還會(huì)按照預(yù)期去執(zhí)行嗎
  • 定時(shí)器如何進(jìn)行時(shí)間糾正
  • 簡(jiǎn)單比較下scheduler.yield

基本的語(yǔ)法

scss
代碼解讀
復(fù)制代碼
setTimeout(code) setTimeout(code, delay) setTimeout(functionRef) setTimeout(functionRef, delay) setTimeout(functionRef, delay, param1) setTimeout(functionRef, delay, param1, param2) setTimeout(functionRef, delay, param1, param2, /* …, */ paramN)

例如我們寫個(gè)最簡(jiǎn)單的

我們來(lái)添加一個(gè)參數(shù)進(jìn)行測(cè)試 如下,可以打印出來(lái)獲取到的參數(shù)params1和params2

返回值

返回值 timeoutID 是一個(gè)正整數(shù),表示由 setTimeout() 調(diào)用創(chuàng)建的定時(shí)器的標(biāo)識(shí)符??梢詫⑦@個(gè)值傳遞給 clearTimeout() 來(lái)取消該定時(shí)器。

我們嘗試在1秒的時(shí)候?qū)imerId進(jìn)行清除,測(cè)試下是否可以正常打印,如你所料,不會(huì)打印timerId內(nèi)的數(shù)據(jù)

進(jìn)階用法

1 防抖(常用于表單提交)

我們?cè)诒韱翁峤坏臅r(shí)候,比如希望表單的提交按鈕在1秒內(nèi)之內(nèi)只生效一次,可以利用settimeout來(lái)實(shí)現(xiàn)。

如下,假如在頁(yè)面上有一個(gè)id為submitBtn的按鈕,添加了一個(gè)點(diǎn)擊事件,當(dāng)1秒內(nèi)每次點(diǎn)擊都會(huì)清除之前的timeoutId,不會(huì)執(zhí)行提交的邏輯。從而確保只有在最后一次點(diǎn)擊后的1秒內(nèi)沒(méi)有再次點(diǎn)擊時(shí),才會(huì)執(zhí)行實(shí)際的操作。

javascript
代碼解讀
復(fù)制代碼
    let submitBtn = document.getElementById("submitBtn");     let timeoutId;     function onTest() {         if (timeoutId) {             clearTimeout(timeoutId);         }         timeoutId = setTimeout(function() {             // 在這里編寫提交邏輯             alert("按鈕被點(diǎn)擊了!");         }, 1000);     }     submitBtn.addEventListener("click", onTest);

2 優(yōu)先展示用戶希望看到的內(nèi)容(利用JS事件機(jī)制)

假如我們有一個(gè)人員的新增表單,部門樹(shù)的下拉框有10K條數(shù)據(jù),假如我們還沒(méi)有虛擬下拉樹(shù),數(shù)據(jù)的渲染會(huì)很慢, 打開(kāi)這個(gè)新增的表單可能會(huì)有3到5S的延遲后表單才會(huì)打開(kāi)。

我們可以將這個(gè)部門樹(shù)的下拉值綁定寫在了settimeout內(nèi),等主線程的任務(wù)執(zhí)行后,再執(zhí)行綁定部門樹(shù)的操作,可以優(yōu)先將其他的內(nèi)容展示出來(lái)后再進(jìn)行部門樹(shù)的綁定。

3 替代setInterval防止請(qǐng)求阻塞

比如我們有個(gè)需求: 1秒的間隔輪詢服務(wù)器,頁(yè)面展示內(nèi)容

正常的話可以用setInterval沒(méi)什么問(wèn)題,

假如請(qǐng)求的接口可能因網(wǎng)絡(luò)延遲、服務(wù)器無(wú)響應(yīng)以及許多其他的問(wèn)題而導(dǎo)致請(qǐng)求無(wú)法在分配的時(shí)間內(nèi)完成(假如服務(wù)器處理了3秒)

我們把請(qǐng)求的間隔設(shè)置為1秒,實(shí)際的接口在2秒多,就會(huì)造成請(qǐng)求的阻塞,其實(shí)我們想實(shí)現(xiàn)的是在一次接口請(qǐng)求結(jié)束后再發(fā)起下一次請(qǐng)求

如下方的截圖

接口固定在大約2秒返回,就會(huì)導(dǎo)致永遠(yuǎn)有幾個(gè)請(qǐng)求在阻塞,跟我們的預(yù)想不同

我們對(duì)上面的代碼進(jìn)行改造如下

 實(shí)現(xiàn)如果如下,我們保證有一個(gè)請(qǐng)求在pending,會(huì)在一個(gè)請(qǐng)求發(fā)出后,再進(jìn)行發(fā)送下一次請(qǐng)求

代碼解釋如下

在上面的代碼片段中,聲明了一個(gè)具名函數(shù) loop(),并被立即執(zhí)行。loop() 在完成代碼邏輯的執(zhí)行后,會(huì)在內(nèi)部遞歸調(diào)用 setTimeout()。雖然該模式不保證以固定的時(shí)間間隔執(zhí)行,但它保證了上一次定時(shí)任務(wù)在遞歸前已經(jīng)完成。

可能遇到的場(chǎng)景

1 settimeout這個(gè)定時(shí)器準(zhǔn)嗎

答案:正常場(chǎng)景下是準(zhǔn)的,某些場(chǎng)景下是不準(zhǔn)的,

有很多因素會(huì)導(dǎo)致超時(shí)比設(shè)定的預(yù)期值更久 如需查看更多的原因點(diǎn)擊我

嵌套多次的時(shí)候會(huì)有4ms的延遲(可以點(diǎn)擊下方的例子進(jìn)行測(cè)試)

點(diǎn)擊我直接看在線例子

當(dāng)嵌套多次的結(jié)果如下,就不做詳細(xì)介紹了,了解就行。目前我沒(méi)想到哪些場(chǎng)景下settimeout會(huì)被嵌套調(diào)用5次,就不做繼續(xù)研究,我們只需要知道這個(gè)概念就行,等出現(xiàn)這個(gè)問(wèn)題了有個(gè)排查方向就行

主線程有耗時(shí)的任務(wù)

我們做個(gè)實(shí)驗(yàn),我們對(duì)id為main對(duì)dom進(jìn)行2萬(wàn)次的修改innerHtml,在控制臺(tái)打印時(shí)間,

原本2秒變?yōu)榱?秒,所以settimeout 有時(shí)候并不會(huì)按照預(yù)期的時(shí)間間隔來(lái)執(zhí)行

這里其實(shí)就涉及到了js的事件為單線程機(jī)制,我們用performance簡(jiǎn)單分析下,看到有個(gè)3865ms的parse HTML的,然后執(zhí)行Run Microtasks也就是微任務(wù),也就是等我們的同步任務(wù)執(zhí)行后,再去執(zhí)行settimeout內(nèi)的東西

在非活動(dòng)標(biāo)簽的tab,待機(jī)下的settimeout還會(huì)按照預(yù)期執(zhí)行嗎?

以下的測(cè)試是在chrome的mac版本進(jìn)行測(cè)試

代碼很簡(jiǎn)單,寫了個(gè)2秒的定時(shí)器

待機(jī)狀態(tài)

tab非激活

過(guò)幾分鐘后,定時(shí)器會(huì)從2秒變?yōu)?分鐘

由此我們得知,在瀏覽器激活的時(shí)候,settimeout 會(huì)按照我們的預(yù)期去執(zhí)行,在非激活(tab不選中過(guò)段時(shí)間、電腦處于待機(jī)狀態(tài))下,定時(shí)器會(huì)按照1min一次去執(zhí)行,

但是有種特殊場(chǎng)景,audio假如正在播放,此時(shí)頁(yè)面的settimeout會(huì)被當(dāng)作激活狀態(tài)

settimeout 時(shí)間糾正

當(dāng)然,因?yàn)閖s的事件機(jī)制,settimeout存在時(shí)間偏差,就會(huì)存在時(shí)間糾正,下面介紹了兩個(gè)js的時(shí)間糾正方式,雖然我試用下來(lái)不太理想,也可能是我的姿勢(shì)不對(duì),有更好的方式歡迎和我討論

計(jì)算時(shí)間差(并不能完全避免,只能糾正)

直接在網(wǎng)上抄寫了個(gè)例子。 使用 setTimeout 進(jìn)行計(jì)時(shí),每次計(jì)時(shí)都會(huì)用系統(tǒng)時(shí)間修復(fù)時(shí)間差

js
代碼解讀
復(fù)制代碼
  function timer_setTimeout() {     const speed = 1000; // 設(shè)置定時(shí)器的間隔速度為1000毫秒(1秒)     let countTime = 0; // 初始化計(jì)時(shí)器計(jì)數(shù)變量     let start = new Date().getTime(); // 記錄計(jì)時(shí)開(kāi)始時(shí)的時(shí)間戳     // 定義計(jì)時(shí)器的執(zhí)行函數(shù)     function run() {       countTime++; // 每次執(zhí)行時(shí)遞增計(jì)時(shí)器的計(jì)數(shù)       // 計(jì)算按照計(jì)時(shí)器當(dāng)前速度實(shí)際經(jīng)過(guò)的時(shí)間(countTime * 速度)       let realTime = (countTime * speed);       // 計(jì)算從計(jì)時(shí)開(kāi)始到現(xiàn)在系統(tǒng)經(jīng)過(guò)的時(shí)間       let sysTime = (Date.now() - start);       // 計(jì)算實(shí)際時(shí)間和理想時(shí)間之間的差異       let patch = (sysTime - realTime);       // 使用系統(tǒng)時(shí)間進(jìn)行修復(fù),調(diào)整下一次setTimeout的延遲時(shí)間       // 通過(guò)設(shè)置speed - diff,嘗試校正setTimeout的延遲,以補(bǔ)償偏差       window.setTimeout(run, (speed - patch));       // 更新頁(yè)面元素timeoutDom的文本內(nèi)容,顯示當(dāng)前計(jì)時(shí)器的值       timeoutDom.innerText = `setTimeout: ${countTime}`;     }     // 啟動(dòng)計(jì)時(shí)器,初始調(diào)用run函數(shù),并設(shè)置延遲為speed     window.setTimeout(run, speed);   }   // 調(diào)用函數(shù),創(chuàng)建并啟動(dòng)setTimeout計(jì)時(shí)器   timer_setTimeout();

webworker(測(cè)試下來(lái)效果不好)

javascript
代碼解讀
復(fù)制代碼
 console.log(new Date());  for (let index = 0; index < 20000; index++) {    document.getElementById('main').innerHTML += index;  }  function timer_worker() {    // 創(chuàng)建一個(gè)Blob對(duì)象,用于生成一個(gè)可以在Web Worker中執(zhí)行的JavaScript代碼URL    const blob = new Blob(      [        `let countTime = 0;      self.setInterval(() => { // 在Web Worker的上下文中設(shè)置一個(gè)定時(shí)器        countTime++; // 每次定時(shí)器觸發(fā)時(shí)遞增計(jì)數(shù)器        self.postMessage(countTime); // 使用postMessage方法發(fā)送計(jì)數(shù)器的值到主線程      }, 5000);` // 定時(shí)器的時(shí)間間隔設(shè)置為1秒      ],      { type: 'application/javascript' }    ); // 指定Blob的內(nèi)容類型為JavaScript    // 使用URL.createObjectURL方法創(chuàng)建一個(gè)可以被Web Worker使用的URL    const worker = new Worker(URL.createObjectURL(blob));    // 設(shè)置Web Worker的onmessage事件處理器    // 當(dāng)Web Worker使用postMessage發(fā)送消息時(shí),該處理器會(huì)被觸發(fā)    worker.onmessage = (ev) => {      // 更新DOM元素workerDom的文本內(nèi)容,顯示從Web Worker接收到的計(jì)時(shí)器值      console.log(new Date() + ` worker: ${ev.data}`);    };  }  timer_worker();

遇到長(zhǎng)的任務(wù)的時(shí)候,還是會(huì)延遲執(zhí)行

scheduler.yield

在查找 setTimeout 的資料的時(shí)候,發(fā)現(xiàn)了有一個(gè)比較好的東西,scheduler.yield, 感興趣的老板可以點(diǎn)擊我進(jìn)行體驗(yàn),目前兼容性不好(24年8月21日的才支持),不做詳細(xì)介紹。

兼容性如下 

 總結(jié)一句話

使用 setTimeout 是將事件插入在隊(duì)列的結(jié)尾。yield而是發(fā)送到隊(duì)列的前面。這樣,既可以讓步以提高網(wǎng)站上的輸入響應(yīng)速度,又可以確保在讓步完成的工作不會(huì)延遲。

參考文檔

總結(jié)

  1. setTimeout 可以實(shí)現(xiàn)延遲的一些事件,比如多少秒后返回首頁(yè)等
  2. setTimeout 可以通過(guò)一定時(shí)間內(nèi)事件只執(zhí)行一次實(shí)現(xiàn)防抖
  3. setTimeout 可以替代 setInterval實(shí)現(xiàn)更好的輪詢
  4. setTimeout 可以通過(guò)js事件的異步機(jī)制,優(yōu)先展示用戶關(guān)注的內(nèi)容
  5. setTimeout 的事件定時(shí)器在某些場(chǎng)景下定時(shí)器不準(zhǔn),大部分場(chǎng)景下是準(zhǔn)的,如果要求比較精確需要可以進(jìn)行時(shí)間差的修正
  6. setTimeout 在熄屏或者非激活tab的場(chǎng)景下,計(jì)時(shí)器會(huì)延長(zhǎng)變?yōu)?min執(zhí)行一次
  7. setTimeout 是把事件插入到尾部,未來(lái)我們可以使用 scheduler.yield的暫停頁(yè)面的操作,提升用戶體驗(yàn) 、

該文章在 2024/12/27 12:39:50 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved