偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

為什么你的 setTimeout 并不像你以為的那樣工作

開發(fā) 前端
在 JavaScript 世界中,??setTimeout?? 常常被視為「延遲執(zhí)行」的萬能工具。但真正掌握它的行為細(xì)節(jié),并不如想象中簡(jiǎn)單。許多開發(fā)者明明寫下了 ??setTimeout(fn, 1000)??,卻驚訝于它“沒準(zhǔn)時(shí)”、“被跳過”甚至“完全不執(zhí)行”。

在 JavaScript 世界中,setTimeout 常常被視為「延遲執(zhí)行」的萬能工具。但真正掌握它的行為細(xì)節(jié),并不如想象中簡(jiǎn)單。許多開發(fā)者明明寫下了 setTimeout(fn, 1000),卻驚訝于它“沒準(zhǔn)時(shí)”、“被跳過”甚至“完全不執(zhí)行”。

? 基礎(chǔ)誤解:setTimeout(fn, 1000) ≠ 準(zhǔn)時(shí)執(zhí)行

setTimeout 并不保證回調(diào)函數(shù)會(huì)在指定的毫秒數(shù)后立即執(zhí)行。

它的真實(shí)含義是:


“將 fn 在至少 delay 毫秒后,加入任務(wù)隊(duì)列(callback queue),并等待主線程空閑時(shí)執(zhí)行?!?/span>

例子:看似直覺的錯(cuò)覺

console.log("Start");

setTimeout(() => {
  console.log("Timeout!");
}, 0);

console.log("End");

輸出:

Start
End
Timeout!

原因很簡(jiǎn)單:即使 delay 設(shè)置為 0,任務(wù)也只能在當(dāng)前執(zhí)行棧(call stack)清空后被調(diào)度執(zhí)行。

?? 主線程阻塞會(huì)直接影響定時(shí)器

考慮下面的代碼:

console.log("Start");

setTimeout(() => {
  console.log("Timeout!");
}, 1000);

const now = Date.now();
while (Date.now() - now < 3000) {
  // 模擬阻塞主線程
}

console.log("End");

盡管延遲設(shè)置為 1s,回調(diào)實(shí)際要等 超過 3 秒 后才會(huì)執(zhí)行。這就是 JavaScript 的單線程模型導(dǎo)致的“延遲漂移”現(xiàn)象。

?? 重復(fù)使用 setTimeout 的隱藏陷阱

部分開發(fā)者使用遞歸實(shí)現(xiàn)定時(shí)器:

function tick() {
  console.log("Tick");
  setTimeout(tick, 1000);
}

tick();

雖然看起來每秒執(zhí)行一次,但如果 tick 中包含耗時(shí)操作,下一次調(diào)度就會(huì)被推遲。這種方式并不適合對(duì)時(shí)間敏感的場(chǎng)景。

更推薦的做法:

  • 需要精確間隔: 使用 setInterval(需注意累積誤差)
  • 需要?jiǎng)赢嬃鲿承裕?/span> 使用 requestAnimationFrame 或基于時(shí)間差的計(jì)算

“定時(shí)器根本沒觸發(fā)” 的常見原因

當(dāng) setTimeout 根本沒執(zhí)行時(shí),可能不是代碼寫錯(cuò),而是以下情況導(dǎo)致:

  • React/Vue 等框架中組件卸載導(dǎo)致定時(shí)器被清除
  • 主動(dòng)或間接調(diào)用了 clearTimeout
  • 瀏覽器處于后臺(tái)標(biāo)簽頁,觸發(fā)了定時(shí)器節(jié)流
  • 運(yùn)行環(huán)境并不是真正的瀏覽器(如 Web Worker、Node.js 等)

Chrome、Safari、Firefox 等現(xiàn)代瀏覽器均會(huì)對(duì)非活動(dòng)標(biāo)簽頁的定時(shí)器進(jìn)行強(qiáng)制降頻或延遲,有時(shí)甚至高達(dá) 60 秒。

經(jīng)典 Closure 閉包陷阱

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

預(yù)期輸出: 0, 1, 2, 3, 4實(shí)際輸出: 5, 5, 5, 5, 5

原因:var 是函數(shù)作用域,循環(huán)結(jié)束后 i 的值已經(jīng)是 5,所有回調(diào)共享同一個(gè)變量引用。

正確寫法:

使用 let(塊級(jí)作用域):

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}

或使用 IIFE 包裝作用域:

for (var i = 0; i < 5; i++) {
  (function(i) {
    setTimeout(() => {
      console.log(i);
    }, 1000);
  })(i);
}

總結(jié):關(guān)于 setTimeout 的關(guān)鍵認(rèn)知

規(guī)則

描述

非精確性

setTimeout(fn, t)

 是最早何時(shí)加入隊(duì)列,不是保證準(zhǔn)時(shí)執(zhí)行

單線程限制

若主線程忙,定時(shí)器就會(huì)等待,導(dǎo)致延遲漂移

閉包陷阱

循環(huán)中使用 var 時(shí),所有回調(diào)共享同一個(gè)變量

瀏覽器節(jié)流

后臺(tái)標(biāo)簽頁可能觸發(fā)延遲機(jī)制,長(zhǎng)時(shí)間不執(zhí)行

非阻塞調(diào)度

setTimeout

 是調(diào)度機(jī)制,不是強(qiáng)制“倒計(jì)時(shí)觸發(fā)器”


責(zé)任編輯:武曉燕 來源: 大遷世界
相關(guān)推薦

2020-06-27 17:33:42

云計(jì)算技術(shù)安全

2022-03-21 18:27:38

Linux計(jì)算機(jī)函數(shù)

2022-06-07 14:55:23

蘋果M2 芯片MacBook

2017-12-18 12:45:41

前端高薪IT行業(yè)

2019-08-07 18:45:40

語音助手TTS前端

2021-01-13 10:51:08

PromissetTimeout(函數(shù)

2010-09-02 09:32:26

私有云

2023-07-28 14:41:07

技術(shù)方案

2018-12-18 09:14:13

區(qū)塊鏈開源比特幣

2025-04-03 07:00:00

網(wǎng)絡(luò)安全物聯(lián)網(wǎng)安全智能安全

2012-04-04 11:24:45

Google

2018-05-08 06:51:02

2023-04-26 07:43:23

SleepCPU內(nèi)核

2021-02-05 11:08:06

云計(jì)算

2019-10-12 09:35:37

程序員人生第一份工作大學(xué)

2021-08-10 07:00:00

Nacos Clien服務(wù)分析

2017-11-29 18:16:15

高并發(fā)ERP態(tài)牛

2013-05-27 09:15:07

2016-08-19 01:59:22

APPAPM用戶

2019-06-04 06:34:50

物聯(lián)網(wǎng)IOT技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)