setInterval的任務正在執行時,setTimeout的任務會等待前者完成后再執行,這樣會造成2個計時器的時間精度出錯?

setInterval,setTimeout 2種計時器在同一個頁面處理任務,想看下精度用時情況。


setInterval的任務正在執行時,setTimeout的任務會等待前者完成后再執行,這樣會造成2個計時器的時間精度出錯?本來settimeout啟動0.5秒,執行2秒,每次2.5秒精確,因為用了setInterval,會造成浪費更多時間?

已完成思考

在 JavaScript 中,由于單線程事件循環的特性,setInterval?和?setTimeout?的時間精度確實會受到任務執行時長和其他任務阻塞的影響,尤其是當存在長時間運行的任務時,兩者的行為差異和相互干擾會導致時間精度進一步下降,甚至出現 “浪費時間” 的現象。下面結合你的場景具體分析:

一、單線程機制:定時器精度的 “先天限制”

JavaScript 是單線程的,所有任務(包括定時器回調、事件處理等)都需要在同一個主線程中排隊執行。當一個任務正在執行時,其他任務必須進入事件隊列等待,直到當前任務完成后才能被執行。這意味著:
定時器的 “預期觸發時間” 只是 “最早可能執行時間”,而非 “精確執行時間”。如果此時主線程被其他任務占用(比如你的場景中每次任務需要執行 2 秒),定時器回調會被延遲到主線程空閑后才執行,導致實際執行時間比預期晚。

二、setInterval?的 “無防堆積” 特性:精度問題的放大器

你的場景中?setInterval?被設置為每 0.5 秒觸發一次,而任務本身需要執行 2 秒(遠長于間隔時間)。setInterval?的核心特性是:它的時間間隔是從 “上一次觸發時刻” 開始計算的,而非 “上一次執行完成時刻”。這會導致嚴重的任務堆積問題:

  • 預期行為:每 0.5 秒觸發一次,每次執行 2 秒。
  • 實際行為
    第 1 次觸發后,任務開始執行(耗時 2 秒);
    0.5 秒后(第 0.5 秒),setInterval?會強制添加第 2 次任務到隊列(即使第 1 次還在執行);
    又過 0.5 秒(第 1.0 秒),添加第 3 次任務到隊列;
    以此類推,直到第 1 次任務在第 2 秒完成后,隊列中堆積的第 2、3、4 次任務會 “連續執行”,導致實際觸發間隔完全混亂,且總耗時遠超過預期。

這種 “無防堆積” 的特性會讓?setInterval?的時間精度極差 —— 它不關心前一次任務是否完成,只會機械地按固定間隔添加任務,最終導致任務 “扎堆執行”,實際間隔和預期間隔完全脫節。

三、setTimeout?遞歸調用:相對更可控的精度

如果用?setTimeout?遞歸實現(即每次任務完成后,再通過?setTimeout?安排下一次任務),行為會更可控:

  • 邏輯:第 1 次任務執行完成后(耗時 2 秒),通過?setTimeout?延遲 0.5 秒觸發第 2 次任務,以此類推。
  • 實際間隔:每次任務的 “實際間隔” 是 “任務執行時間(2 秒)+ 延遲時間(0.5 秒)”,總間隔穩定在 2.5 秒左右(理想狀態下)。

這是因為?setTimeout?遞歸的間隔是從 “上一次任務完成時刻” 開始計算的,不會像?setInterval?那樣在任務執行期間堆積新任務。但注意:如果存在其他任務(比如?setInterval?的任務)阻塞主線程,setTimeout?的回調同樣會被延遲,導致實際間隔變長。

四、兩者同時運行:相互阻塞導致精度 “雪上加霜”

當?setInterval(無防堆積)和?setTimeout?同時調用同一個耗時 2 秒的任務時,由于單線程限制,它們的回調會在事件隊列中排隊,互相阻塞,導致:

  1. setInterval?的堆積任務搶占資源
    setInterval?每 0.5 秒添加一個任務到隊列,即使前一個任務還在執行。這些堆積的任務會占用主線程,導致?setTimeout?的回調被延遲更久。例如:

    • setTimeout?預期 0.5 秒后執行,但此時隊列中可能有?setInterval?堆積的 3 個任務(每個 2 秒),setTimeout?的回調需要等待 3×2=6 秒后才能執行,實際間隔變成 6.5 秒,完全偏離預期。
  2. setTimeout?的長任務反堵?setInterval
    反過來,setTimeout?的 2 秒任務執行時,setInterval?仍在按 0.5 秒間隔添加新任務到隊列,導致?setInterval?的任務堆積更多,進一步加劇主線程阻塞。

  3. 總耗時大幅增加
    原本?setTimeout?遞歸單獨運行時,4 次任務總耗時約 4×2.5=10 秒(理想狀態);但如果和?setInterval?同時運行,由于任務排隊阻塞,總耗時可能遠超 10 秒,且兩者的實際執行次數和時間間隔都會變得混亂。

五、為什么會 “浪費更多時間”?

“浪費時間” 本質上是任務阻塞導致的等待時間。在你的場景中:

  • setInterval?的無防堆積特性會產生大量 “無效排隊任務”,這些任務在主線程空閑后會連續執行,占用本可以給?setTimeout?或其他任務的時間;
  • 兩者的任務都是耗時 2 秒的長任務,疊加后主線程被長時間占用,導致后續任務(包括定時器回調)的等待時間被無限拉長,實際執行時間與預期時間的偏差越來越大,最終總耗時遠超過理論值。

總結:setInterval?vs?setTimeout?精度對比

特性setInterval(無防堆積)setTimeout?遞歸調用
間隔計算起點上一次觸發時刻(不考慮執行耗時)上一次執行完成時刻(考慮執行耗時)
任務堆積風險高(間隔 < 執行耗時會導致任務排隊)低(每次完成后才安排下一次,無堆積)
時間精度差(受執行耗時和堆積影響,偏差隨時間增大)較好(間隔相對穩定,但仍受其他任務阻塞影響)
與其他定時器共存時易相互阻塞,精度進一步下降,總耗時增加相對獨立,但仍可能被其他任務(如?setInterval?堆積任務)阻塞

結論:在存在長任務(如 2 秒執行時間)的場景中,setInterval?的無防堆積特性會導致任務堆積和時間精度嚴重下降;而?setTimeout?遞歸調用的精度相對更可控,但兩者同時運行時,單線程的阻塞會讓彼此的精度都大幅降低,最終導致實際執行時間遠超過預期,造成 “時間浪費”。

如果需要更高的時間精度,通常建議:

  1. 避免使用?setInterval?執行長任務,改用?setTimeout?遞歸調用;
  2. 盡量縮短單次任務的執行時間(比如拆分長任務為微任務);
  3. 必要時使用 Web Worker 分擔計算壓力,避免主線程阻塞。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95325.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95325.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95325.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DeepSeek-R1-0528 推理模型完整指南:領先開源推理模型的運行平臺與選擇建議

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

【AI實戰】從零開始微調Qwen2-VL模型:打造制造業智能安全巡檢系統

【AI實戰】從零開始微調Qwen2-VL模型&#xff1a;打造制造業智能安全巡檢系統&#x1f3af; 項目背景與目標&#x1f6e0; 環境準備硬件要求軟件環境搭建&#x1f4ca; 數據準備&#xff1a;構建高質量訓練集第一步&#xff1a;提取規章制度知識第二步&#xff1a;創建標注數據…

5 重復匹配

在前幾章里&#xff0c;我們學習了如何使用各種元字符和特殊的字符集合去匹配單個字符。本章將學習如何匹配多個連續重復出現的字符或字符集合。5.1 有多少個匹配你現在已經學會了正則表達式的模式匹配中的基礎知識&#xff0c;但目前所有的例子都有一個非常嚴重的局限。請大家…

【瀏覽器兼容性處理】

瀏覽器兼容性處理是前端開發中重要的一環&#xff0c;指解決不同瀏覽器&#xff08;或同一瀏覽器不同版本&#xff09;對HTML、CSS、JavaScript解析執行存在差異&#xff0c;導致頁面顯示異常或功能失效的問題。以下是常見問題及系統的處理方案&#xff1a; 一、常見兼容性問題…

Android組件化實現方案深度分析

組件化是解決大型應用代碼臃腫、耦合嚴重、編譯緩慢、團隊協作困難等問題的關鍵架構手段&#xff0c;其核心在于 模塊化拆分、解耦、獨立開發和按需集成。 一、 組件化的核心目標與價值 解耦與高內聚&#xff1a; 將龐大單體應用拆分為功能獨立、職責單一的模塊&#xff08;組件…

外賣:重構餐飲的線上服務密碼

外賣不是 “把堂食菜裝進盒子送出去”&#xff0c;而是 “用線上化服務重構餐飲與用戶連接” 的經營模式 —— 它的核心&#xff0c;是 “讓用戶在家也能吃到‘像在店里一樣好’的體驗”。一、外賣的底層邏輯用戶點外賣&#xff0c;本質是 “想在家獲得‘餐廳級體驗’”&#x…

C++——高性能組件

文章目錄一、什么是高性能組件1.1 C 中高性能組件的核心設計原則1.2 常見的 C 高性能組件 / 庫舉例1.3 實現高性能組件的關鍵工具二、定時器2.1 什么是用戶態定時器2.2 為什么要使用用戶態定時器2.3 高性能用戶態定時器的實現原理2.3.1 訓練營2.3.1.1 問題解析2.3.1.2 模擬問答…

【軟考中級網絡工程師】知識點之 UDP 協議:網絡通信中的高效輕騎兵

目錄一、UDP 協議簡介二、UDP 協議特點2.1 無連接性2.2 不可靠性2.3 面向數據報2.4 低開銷2.5 廣播支持三、UDP 協議工作原理3.1 UDP 報文格式3.2 UDP 數據傳輸過程四、UDP 協議應用場景4.1 實時音視頻傳輸4.2 在線游戲4.3 DNS 查詢4.4 其他應用場景五、UDP 與 TCP 對比5.1 可靠…

【Node.js從 0 到 1:入門實戰與項目驅動】2.1 安裝 Node.js 與 npm(Windows/macOS/Linux 系統的安裝步驟)

文章目錄 第 2 章:環境搭建 —— 準備你的開發工具 2.1 安裝 Node.js 與 npm(Windows/macOS/Linux 系統的安裝步驟) 一、通用安裝前檢查 二、Windows 系統安裝步驟 方法 1:通過官方安裝包(推薦) 方法 2:通過 nvm-windows 管理多版本(進階) 三、macOS 系統安裝步驟 方法…

C語言相關簡單數據結構:數據結構概念

目錄 1.需要的儲備知識 2.數據結構相關概念 2.1 什么是數據結構 什么是數據&#xff1f; 什么是結構&#xff1f; 概念&#xff1a; 總結&#xff1a; 2.2 為什么需要數據結構&#xff1f; 結論&#xff1a; C語?語法基礎到數據結構與算法&#xff0c;前?已經掌握并…

Docker 詳細介紹及使用方法

Docker 詳細介紹及使用方法 一、Docker 是什么&#xff1f; Docker 是一種開源的應用容器引擎&#xff0c;基于 Go 語言開發并遵從 Apache 2.0 協議開源。它允許開發者將應用程序及其依賴打包到一個輕量級、可移植的容器中&#xff0c;然后發布到任何流行的 Linux 機器上。Dock…

PHP request文件封裝

1.繼承FormRequest 其中id是路由傳參 name是對象中必填校驗<?phpnamespace App\Http\Requests\Admin\User;use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule;class user_info_uptRequest extends FormRequest {public function authorize():…

基于跨平臺的svg組件編寫一個svg編輯器

duxapp 提供了一套跨平臺的 SVG 編輯器組件&#xff0c;支持在多種環境中創建和編輯 SVG 圖形。該編輯器包含以下核心功能&#xff1a; 插入圖片繪制自由路徑添加文本創建基本形狀&#xff08;矩形、圓形、線條等&#xff09;對元素進行移動、縮放和旋轉操作 快速開始 import…

react+echarts實現圖表展示的兩種方法

前言&#xff1a;reactecharts實現圖表展示。1、直接用echarts的插件來實現1&#xff09;安裝npm install echarts2&#xff09;使用1、useEffect是react中集合onload/watch監聽等方法與一體的hook函數&#xff0c;他的第二個參數是空數組&#xff0c;則等同于onload&#xff0…

Apache 服務器基礎配置與虛擬主機部署

Apache 服務器基礎配置與虛擬主機部署 Apache 的核心定位與作用&#xff1a; Apache 的核心功能是處理 HTTP 請求并提供 Web 資源&#xff0c;是客戶端&#xff08;如瀏覽器&#xff09;與 Web 服務器之間的 “中間人”&#xff1a; 接收客戶端通過 HTTP/HTTPS 協議發送的請求…

線性代數 · 矩陣 | 最小多項式

注&#xff1a;本文為 “矩陣 | 最小多項式” 相關合輯。 略作重排&#xff0c;如有內容異常&#xff0c;請看原文。 最小多項式 橘子蜂蜜 于 2019-05-22 22:48:25 發布 根據哈密頓 - 凱萊&#xff08;Hamilton - Cayley&#xff09;定理&#xff0c;任給數域 PPP 上的一個 …

docter的使用、vscode(cursor)和docker的連接,詳細分析說明

目錄 一、基本命令 二、用案例來學習使用方法 &#x1f680; Pull Python 3.11 鏡像并創建命名容器 &#x1f4cb; 其他有用命令 在容器中安裝依賴 三、直接在鏡像中安裝依賴&#xff08;創建自己定制的鏡像&#xff09; 四、在 cursor 中選用容器作為編譯器 五、對于整…

如何使用AI大語言模型解決生活中的實際小事情?

我們總以為AI是遙不可及的未來科技&#xff0c;卻忽視了它早已成為生活中最實用的“隱形助手”。在信息爆炸的今天&#xff0c;我們每天被無數生活瑣事包圍&#xff1a;一封專業郵件反復修改措辭、孩子突如其來的數學難題、冰箱里僅剩的食材如何搭配、旅行行程的繁瑣規劃……這…

關于微信小程序的筆記

1.需要獲取demo素材圖片方法&#xff08;2,3&#xff09;2.使用逆向工具進行解包沒有安裝node的需要安裝一下安裝npm i -g wedecode0.8.0-beta.3獲取小程序文件存放路徑/Users/lin/Library/Containers/com.tencent.xinWeChat/Data/.wxapplet/packages/wx060ecb4f74eac0da根據具…

課堂筆記:吳恩達的AI課(AI FOR EVERYONE)-W2 AI項目工作流程

課堂筆記&#xff1a;吳恩達的AI課&#xff08;AI FOR EVERYONE&#xff09;-W2 AI項目工作流程 一、如何開始一個AI項目&#xff1f; 1、建設項目工作流程 2、選擇合適的AI項目 3、為這個項目收集數據和組織團隊二、AI項目的工作流程 &#xff08;1&#xff09;機器學習項目的…