發現 JavaScript 計時器

setTimeout()

在撰寫 JavaScript 代碼時,您可能希望延遲執行某個函數。

這就是 setTimeout 的作用。您可以指定稍後要執行的回調函數以及要延遲執行的時間,以毫秒為單位。

setTimeout(() => {
  // runs after 2 seconds
}, 2000);

setTimeout(() => {
  // runs after 50 milliseconds
}, 50);

此語法定義了一個新的函數。您可以在其中調用任何其他函數,或者您可以傳遞現有的函數名稱和一組參數

const myFunction = (firstParam, secondParam) => {
  // do something
};

// runs after 2 seconds
setTimeout(myFunction, 2000, firstParam, secondParam);

setTimeout 返回計時器 ID。這通常不被使用,但您可以將此 ID 存儲起來,並在需要刪除此預定的函數執行時清除它

const id = setTimeout(() => {
  // should run after 2 seconds
}, 2000);

// I changed my mind
clearTimeout(id);

零延遲

如果將超時延遲指定為 0,則回調函數將盡快執行,但在當前函數執行之後執行

setTimeout(() => {
  console.log('after ');
}, 0);

console.log(' before ');

此代碼將打印

before
after

這對於避免在執行密集任務時阻塞 CPU 並允許在執行繁重計算時排隊函數以讓其他函數執行尤其有用。

某些瀏覽器(如 IE 和 Edge)實現了一個 setImmediate() 方法,執行的功能與這相同,但這並非標準,且在其他瀏覽器中 無法使用。但在 Node.js 中是標準功能。

setInterval()

setInterval 是一個與 setTimeout 相似的函數,但有一點不同:它不僅在指定的時間間隔(以毫秒為單位)運行回調函數一次,而是會持續運行。

setInterval(() => {
  // runs every 2 seconds
}, 2000);

上面的函數每 2 秒運行一次,除非您使用 clearInterval 停止它,並傳遞 setInterval 返回的間隔 ID。

const id = setInterval(() => {
  // runs every 2 seconds
}, 2000);

clearInterval(id);

通常在 setInterval 回調函數內部調用 clearInterval,讓它自動決定是否繼續運行。例如,此代碼會運行某些操作,除非 App.somethingIWait 具有值 arrived

const interval = setInterval(() => {
  if (App.somethingIWait === 'arrived') {
    clearInterval(interval);
  }
  // otherwise do things
}, 100);

遞迴的 setTimeout

setInterval 每 n 毫秒啟動一次函數,不考慮函數何時完成其執行。

如果一個函數始終花費相同的時間,這沒有問題。

setInterval working fine

也許函數的執行時間會根據網絡條件等因素而不同。

setInterval varying duration

也許一次長時間的執行會與下一次重疊。

setInterval overlapping

為了避免這種情況,您可以安排一個遞迴的 setTimeout 在回調函數完成後調用。

const myFunction = () => {
  // do something

  setTimeout(myFunction, 1000);
};

setTimeout(myFunction, 1000);

以實現這種情況

Recursive setTimeout

setTimeoutsetInterval 在 Node.js 中可用,通過 Timers 模塊提供。

Node.js 也提供了 setImmediate(),它等效於使用 setTimeout(() => {}, 0),主要用於與 Node.js 事件循環一起使用。