【JavaScript】面試手撕節流

引入

上篇我們講了防抖,這篇我們就談談防抖的好兄弟 – 節流。這里在老生常談般的提一下他們兩者之間的區別,順帶給讀者鞏固下。

PS: 開源節流中節流與這個技術上的節流,個人認為本質上是一樣的。

  • 開源節流的節流指的是節省公司的金錢開支。
  • 前端技術上的節流指的是稀釋函數的調用頻率,節省CPU的開支。

區別

  • 節流: N 秒內只運行一次,若在N秒內重復觸發,只有第一次生效
  • 防抖: N 秒后在執行該事件,若在N秒內被重復觸發,則重新計時

不過我認為還是防抖那篇文章有個讀者的評論更顯生動 🐶, 在此對該讀者表示感謝🙏。

  • 節流: 可以看做攻擊間隔,點的再快沒打出來也不會同時攻擊兩次。
  • 防抖: 可以理解為回城,每點一下就要重新跑.

節流例子

這里我舉兩個常見的🌰,大家有什么更好的🌰可以在評論里回復
這個王者榮耀的攻擊例子也算是節流,不過這個我就不舉了。🐶

生活例子

這里跟大家舉一個生活例子,更顯生動。

我們知道一般女神回復舔🐶的概率都是比較低的,假設女神每天回復舔🐶一次。也就是說如果今天女生已經回復過了,那么無論舔🐶發再多的信息對方也是不會回的。今天的次數已經消耗完畢了,也只能等明天才能刷新。

短信驗證

我們知道短信驗證是在生活中很常見,其實短信驗證便用到了節流的技術。
因為發短信其實是要錢的,為了避免一個用戶重復點擊導致發出多條短信就要使用節流。比如獲取一次驗證碼的有效時間為60秒,則60秒內這個發送短信的方法不能再次觸發。

手撕代碼

xdm,接下來開始手撕代碼了。這里有兩種實現方式,分別是時間戳實現和定時器實現。

時間戳實現

原理

每次事件觸發都會檢查距離上次執行的時間間隔,如果超過指定的等待時間delay,則執行函數。并且更新上一次執行時間為為當前的時間戳。

代碼
function throttleByTimestamp(fn, wait) {let lastTime = 0; // 用于保存上一次執行的時間戳return function () {const currentTime = new Date().getTime();// 判斷當前時間與上次執行時間差是否大于等待時間if (currentTime - lastTime > wait) {// 如果滿足條件,則執行原函數,并傳遞參數fn.apply(this, arguments);// 更新上一次執行的時間戳為當前時間lastTime = currentTime;}};
}// 使用
const throttledFn = throttleByTimestamp(function () {console.log("節流函數被執行");
}, 500); // 每隔500毫秒執行一次// 等待時間
const waitTime = async (time) => {return new Promise((resolve) => {setTimeout(() => {resolve();}, time);});
};const main = async() => {throttledFn();// 換成 < 500ms的則只會執行一次await waitTime(600);throttledFn();
}main()/*** 輸出:* 節流函數被執行* 節流函數被執行*/

定時器實現

原理

我們在事件觸發時設置一個定時器。

  • 首次事件觸發時,我們設置一個定時器,在等待一段時間后執行函數。
  • 當定時器觸發前,如果有新的事件觸發,我們會檢查是否存在定時器,如果存在則跳過。
  • 當定時器觸發時,會清除當前定時器,確保下一次事件能重新觸發。
代碼

注: 測試例子跟上面的一樣,此處不在貼啦。

function throttleByTimer(fn, delay) {let timer;return function () {const context = this;const args = arguments;if (!timer) {timer = setTimeout(() => {fn.apply(context, args);clearTimeout(timer);timer = null;}, delay);}};
}

時間戳+定時器實現

我們回顧這兩個實現方式,大家有沒有發現這兩個實現方式的區別?

  • 時間戳: 因為是拿當前時間減上一次觸發的時間,所以一旦滿足該條件,事件會立即執行。
  • 定時器: 由于fn.apply的函數寫在了setTimeout里,所以觸發了,也得等delay后才能執行,于是就有了這種事件停止觸發后依然會再一次執行的效果。

如果我們要實現這樣的一個需求,完成一個事件觸發時立即執行,觸發完畢還能執行一次的節流函數該如何做呢?

原理

此處借鑒掘金網友《6個瑞士卷》的分析,個人覺得邏輯寫的很好。于是摘錄了下來。

  • 需要在每個delay時間中一定會執行一次函數,因此在節流函數內部使用開始時間、當前時間與delay來計算remaining
  • remaining <= 0時表示該執行函數了,如果還沒到時間的話就設定在remaining時間后再觸發。
  • 當然在remaining這段時間中如果又一次發生事件,那么會取消當前的計時器,并重新計算一個remaining來判斷當前狀態。
代碼
function throttle(fn, delay) {let timer;let lastTime = 0;return function () {let currentTime = Date.now();// 計算距離上次執行fn到現在過去了多少時間,與delay做比較let remaining = delay - (currentTime - lastTime);const context = this;const args = arguments;// 如果在remaining這段時間在發生,會取消當前的計時器clearTimeout(timer);// 當remaining <= 0時表示該執行函數了if (remaining <= 0) {fn.apply(context, args);lastTime = Date.now();} else {// 如果還沒到時間的話就設定在remaining時間后再觸發timer = setTimeout(fn, remaining);}};
}

借鑒文章

  1. JS簡單實現防抖和節流

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

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

相關文章

databinding雙向綁定原理,Android程序員最新職業規劃

1. Android架構設計模式 MVC架構設計模式&#xff1a;MVC全名是Model View Controller&#xff0c;是模型(model)-視圖(view)-控制器(controller)的縮寫。MVP架構設計模式&#xff1a;MVC全名是Model View Persenter&#xff0c;MVP由MVC演變而來&#xff0c;是現在主流的開發…

小工具——抖音短視頻評論自動同步

很多時候喜歡看抖音的評論&#xff0c;有時候評論也是一個查疑解惑的好地方&#xff0c;很多人也喜歡把抖音的評論集中起來做分析。 因為一個朋友問過我這回事&#xff0c;閑著的時候也研究了下抖音&#xff0c;所以自己做了個小工具&#xff0c;自動同步你觀看的抖音短視頻的…

Gophish+EwoMail 自建釣魚服務器

GophishEwoMail 自建釣魚服務器 文章目錄 GophishEwoMail 自建釣魚服務器1.前提準備2.搭建EwoMail郵件服務器1&#xff09;Centos7 防火墻操作2&#xff09;設置主機名3&#xff09;host配置4&#xff09;安裝EwoMail5&#xff09;獲取DKIM6&#xff09;端口服務介紹7&#xff…

黑馬JavaWeb課程中安裝vue腳手架出現的問題

1 安裝node.js 要想前端工程化&#xff0c;必須安裝node.js&#xff0c;前端工程化的環境。 在成功安裝node.js后&#xff0c; 修改全局包安裝路徑為Node.js安裝目錄&#xff0c; 修改npm鏡像源為淘寶鏡像源&#xff0c;這里出現第一個問題&#xff0c;視頻中給的淘寶鏡像為&…

OnlyOffice Document Server部署的步驟和詳細解說

OnlyOffice Document Server是一個免費的開源辦公套件&#xff0c;支持在線查看和編輯Office文檔。要部署OnlyOffice Document Server&#xff0c;可以通過多種方式進行&#xff0c;包括使用Docker、手動安裝在Linux服務器上&#xff0c;或者直接安裝在Windows服務器上。 以下…

Maven-私服(黑馬學習筆記)

前面我們在講解多模塊開發的時候&#xff0c;我們講到我們所拆分的模塊是可以在同一個公司各個項目組之間進行資源共享的。這個模塊的資源共享&#xff0c;就需要通過我們接下來所講解的Maven的私服來實現。 首先我們先介紹一下什么是私服&#xff0c;以及它的作用是什么。再來…

力扣180 連續出現的數字

如何有效地識別在數據庫中至少連續出現三次的數字&#xff1f; 目錄 題目描述 解題思路 完整代碼 進一步探索 題目描述 表&#xff1a;Logs ---------------------- | Column Name | Type | ---------------------- | id | int | | num | varch…

2024最新EasyRecovery磁盤數據恢復軟件功能全面介紹

一、軟件概述 EasyRecovery磁盤數據恢復軟件是一款專業的數據恢復工具&#xff0c;旨在幫助用戶從各種存儲設備中恢復因各種原因丟失的數據。該軟件憑借其強大的恢復能力、操作簡便和高效穩定的性能&#xff0c;得到了廣大用戶的認可。 EasyRecovery-mac最新版本下載:https://…

數據庫的簡單了解及介紹

數據庫&#xff08;Database&#xff09; 1.其本質是一個文件系統。保存了一系列有組織的數據 2.根據數據的結構處理&#xff0c;存儲&#xff0c;管理數據的倉庫 3.隨著時代的發展&#xff0c;數據管理不再僅僅是存儲和管理數據&#xff0c; 漸漸成為用戶所需要的各種數據管理…

go 設置滾動日志

方案 通過 log/slog 實現結構化日志生成&#xff0c;這是go1.21中推出的新特性&#xff1b;通過 lumberjack 實現日志文件分割。 示例 package mainimport ("gopkg.in/natefinch/lumberjack.v2""log/slog""os""path/filepath" )fun…

工業人工智能需要注意的10件事

我們無法逃避人工智能這個風口&#xff0c;宣傳人工智能軟件的廣告鋪天蓋地&#xff0c;似乎每個供應商都在推出最新的工具包&#xff0c;每天都有關于 ChatGPT、Bard 等新用例的文章。似乎全世界都在說&#xff1a;你現在需要人工智能&#xff01; 人工智能確實正在成為自動化…

Fabric V2.5 通用溯源系統——應用后端GIN框架部分設計

本節對Fabric V2.5 通用溯源系統的應用后端部分做一個簡單的介紹,包括目錄結構、文件作用、用戶注冊登錄與農產品信息上鏈過程介紹。此節內容免費發布在TrueTechLabs Fabric學習交流QQ群。 購買專欄前請認真閱讀:《Fabric項目學習筆記》專欄介紹 TrueTechLabs Fabric學習交流…

transformer--編碼器1(掩碼張量、注意力機制、多頭注意力機制)

編碼器部分: 由N個編碼器層堆疊而成每個編碼器層由兩個子層連接結構組成第一個子層連接結構包括一個多頭自注意力子層和規范化層以及一個殘差連接。第二個子層連接結構包括一個前饋全連接子層和規范化層以及一個殘差連接 掩碼張量 什么是掩碼張量 掩代表遮掩&#xff0c;碼…

Ansible的playbook的編寫和解析

目錄 什么是playbook Ansible 的腳本 --- playbook 劇本 實例部署&#xff08;使用playbook安裝啟動httpd服務&#xff09; 1.編寫一個.yaml文件 在主機下載安裝http&#xff0c;將配置文件復制到opt目錄下 運行playbook 在192.168.17.77主機上查看httpd服務是否成功開啟…

DolphinScheduler——蔚來汽車數據治理開發平臺的應用改造

目錄 一、業務痛點 二、應用現狀 三、技術改造 3.1 穩定性 3.1.1 滾動重啟黑名單機制精準路由 3.2 易用性 依賴節點優化 補數任務優化 多 SQL 執行 原文大佬的這篇基于調度系統的數據治理案例有借鑒意義&#xff0c;這里摘抄下來用作學習和知識沉淀。 一、業務痛點 蔚…

Dell R730 2U服務器實踐2:VMWare ESXi安裝

緣起 剛到手邊的一臺Dell R730是三塊硬盤raid0 &#xff0c;把我驚出一身冷汗&#xff0c;準備把它們改組成raid1 或者raid5 。 但是舍不得里面的ESXi 8 &#xff0c;尋找能否把raid0改成raid1 還不掉WSXi的方法&#xff0c;很遺憾沒有找到。那樣只能重裝ESXi了。 ESXi軟件下…

Linux系統上使用C語言創建線程

文章目錄 一、使用C代碼創建線程示例API 二、線程的相關知識2.1 線程 與 進程 的關系2.2 使用線程的理由 一、使用C代碼創建線程 使用pthread_create函數創建線程。 示例 示例&#xff1a;創建一個線程&#xff0c;其作用就是打印線程ID和傳入參數。 //demo1 #include <…

cookie和session對http的作用以及區別

HTTP協議本身是無法判斷用戶身份。所以需要cookie或者session。 1、什么是cookie&#xff1f; cookie 是由 Web 服務器保存在用戶瀏覽器上的文件&#xff08; key-value 格式&#xff09;&#xff0c;可以包含用戶相關的信 息。客戶端向服務器發起請求&#xff0c;就提取瀏覽器…

基于串流技術的p2p共享桌面共享方案

研究遠控有一定時間了&#xff0c;但真正落地運用的不多&#xff0c;所以也不太上心&#xff0c;平時也只是自己diy玩玩&#xff0c;遠程共享看看電視劇。 最近生成式ai大火&#xff0c;直接帶動了gpu應用的相關場景&#xff0c;相關場景&#xff0c;但gpu卡又貴&#xff0c;對…

[記錄]-cannot import name ‘prelu‘ from ‘lasagne.layers‘

問題&#xff1a;cannot import name prelu from lasagne.layers 現有版本&#xff1a;lasagne 0.1,需要更新版本&#xff0c;直接pip installLasagne0.2 目前還不行 需要去源碼下載 命令&#xff1a; pip install --upgrade https://github.com/Theano/Theano/archive/mas…