JavaScript >> Javascript 文檔 >  >> Node.js

👻 setInterval() 的噩夢般危險的默認行為

所以你想每 delay 發送一個 HTTP 請求 毫秒數。簡單的:

setInterval(
  () => {
    doRequest();
  },
  delay,
);

但是如果 delay 是未定義的嗎?

這就是它變得可怕的地方。事實證明,如果 delay 未定義(或 null、NaN 等),它將默認為 1 毫秒!享受你的 DoS 攻擊吧!

我現在已經兩次看到這個問題影響了生產系統,而且這兩個實例都造成了嚴重的損壞並需要緊急維護。

更安全的 setInterval()

如果您擔心這種可能性,可以將 setInterval 替換為更安全的代碼。在初始化期間儘早執行此代碼:

const oldSetInterval = setInterval;
globalThis.setInterval = (callback, delay, ...rest) => {
  if (typeof delay !== 'number' || delay < 1 || delay > 2147483647) {
    throw new Error(`Invalid interval delay: ${delay}`);
  }

  return oldSetInterval(callback, delay, ...rest);
};

這取代了 setInterval 帶有包裝器的全局函數,如果 delay 參數不是數字或超出有效範圍。沒有人喜歡錯誤,但通常比不小心每秒發出 1000 個請求要好!

setInterval() 的其他實現

到目前為止,我一直在談論 Node.js,並且這種行為在 Node.js 文檔中有清楚的記錄。

但是setInterval() 實際上並不是 ECMAScript 標準的一部分,它的一些細節可能會因不同的 JavaScript 環境而異。

您可以執行以下代碼來查看您的環境中的默認延遲是多少:

let prev;
setInterval(() => {
  const cur = new Date().getTime();
  if (prev) {
    console.log(`MS elapsed: ${cur - prev}`);
  }

  prev = cur;
});

看起來在 Firefox 中,默認延遲是 16 毫秒,而在 Chrome 中是 4。雖然 Node.js 文檔指出它是 1 毫秒,但我的測試表明它在 Node.js 中非常不一致,比在瀏覽器中要嚴重得多。我不知道為什麼。

設置超時()

要清楚,是的,setTimeout() 確實有完全相同的問題。

結論

我不知道誰認為默認 delay 是個好主意 到一個低數字。 delay 時拋出錯誤 對我來說無效聽起來是一個更好的主意。但無論如何,它就是這樣!我們只需要了解它並小心。


上一篇
Tutorial JavaScript 教程
  1. Mac 上的 JSLint + TextMate 集成

  2. 是否有使用 JavaScript 取消選擇所有文本的功能?

  3. React 所需的 JavaScript 技能

  4. 結束?

  5. 如何等待 Java 小程序在 Safari 上完成加載?

  6. 如何使用 Node、Express 和 Mongo 構建 REST API

  7. Typescript 中的類型與接口

  1. 如何跳出 JavaScript forEach() 循環

  2. 如何引用作為功能組件的樣式組件?

  3. 如何在幾分鐘內使用 SSR 構建您的第一個微前端

  4. Pt 1:Nuxt 的針:為牙齒和指甲紋身建立網站

  5. RxJs 教程 - 異步類型提前 - Ex 1.2

  6. 解決方案:下一個排列

  7. 如何使用 JavaScript 和 Cheerio.js 構建價格抓取工具

  1. 前端架構中的控制反轉

  2. 介紹 Pudl:一個易於使用的基於 JavaScript 的靜態站點生成器

  3. 幫助構建下一個項目的 API

  4. 如何在 JavaScript 中找出調用者函數?