当前位置:网站首页>Custom throttling function six steps to deal with complex requirements
Custom throttling function six steps to deal with complex requirements
2022-07-02 23:57:00 【An ice cream】
Throttling definition
Some frequently operated events will affect performance ," throttle " Used to control the response time interval , When the event triggers , The corresponding function does not trigger immediately , But at specific intervals , Whenever the response interval for execution is reached , Will execute the response function .
Throttling cases
In online games " Aircraft battle ", Keyboard keys can be used to fire bullets , Hit the keyboard quickly and constantly , The plane will not keep launching , But at certain intervals , To control the distance between bullets . For example, the system is set to fire bullets every second , So even if you hit it in a second 20 Secondary keyboard , Still only send 1 Secondary bullet .
Throttling usage scenario
In the process of programming , Many scenes can be used " throttle ".
- Input box frequently 、 Search for
- Click the button frequently 、 Submission of information , Triggering event
- Listen for browser scrolling Events
- Listen for browser zoom events
When throttling is not used
Here simulate a product search box , We need to call the interface to query the content entered by the user , To give users search tips .
When anti shake is not used , We will directly bind the function to the corresponding event .
// html
<input />
// js Code
const inputEl = document.querySelector("input");
let count = 0;
function inputEvent(event) {
console.log(`${
++count} Time input , The content obtained is :${
event?.target?.value}`);
}
inputEl.oninput = inputEvent;
input Enter... In the box "javascriptcsses6", altogether 16 Characters , So the method calls 16 Time

The performance of this method is very low , Because every time you input a character, you call the interface , The pressure on the server is great ," throttle " To execute the function at a specified time , Avoid the waste of resources caused by multiple implementations .
Self defined throttling function
The principle of throttling function implementation is , Execute the function at the specified time interval .
First step : Basic throttling implementation
Determine the time interval between the current and the last execution of the function , If the specified time interval is exceeded , Just execute the function .
function throttle(fn, interval) {
// Set the initial time as 0
let startTime = 0;
const _throttle = function () {
// Get the current time
let currentTime = new Date().getTime();
// Get the time left ( The distance between the current time and the specified interval )
let restTime = interval - (currentTime - startTime);
// The remaining time is less than or equal to 0 when , Execute function
if (restTime <= 0) {
// Execute the passed in function
fn();
// Assign the current time to the initial time
startTime = currentTime;
}
};
return _throttle;
}
inputEl.oninput = throttle(inputEvent, 2000);
The time interval specified here is 2 Second , namely 2 Execute the function once per second .

But then we found that , Parameters are not passed , actually this The direction of is also wrong
The second step : expand this And parameters
adopt apply Methods to change this The direction of , And passing parameters
function throttle(fn, interval) {
// Set the initial time as 0
let startTime = 0;
const _throttle = function (...args) {
// Get the current time
let currentTime = new Date().getTime();
// Get the time left ( The distance between the current time and the specified interval )
let restTime = interval - (currentTime - startTime);
// The remaining time is less than or equal to 0 when , Execute function
if (restTime <= 0) {
// adopt apply change this Point and pass parameters
fn.apply(this, args);
// Assign the current time to the initial time
startTime = currentTime;
}
};
return _throttle;
}
here this And parameters can be obtained ~

So far , Most usage scenarios of throttling have been implemented , The following functions will be more complex .
The third step : The function is executed immediately
In the above function definition , When entering the first character , The function will execute with high probability , Because the time of inputting the first character minus the initialization time 0 Second , Generally, it will be greater than the set time interval .
If you feel that the function execution when entering the first character is unnecessary , Then you can customize the parameters , To control whether the function will execute immediately .
Parameters leading The control function executes immediately , The default is true.
function throttle(fn, interval, options = {
}) {
let startTime = 0;
// leading The default value is true
const {
leading = true } = options ;
const _throttle = function (...args) {
let currentTime = new Date().getTime();
// When immediate execution is not required , Set the initial value to 0 Of startTime Change to current time
if (!leading && !startTime) {
startTime = currentTime;
}
let restTime = interval - (currentTime - startTime);
if (restTime <= 0) {
fn.apply(this, args);
startTime = currentTime;
}
};
return _throttle;
}
// Pass in leading Parameters
inputEl.oninput = throttle(inputEvent, 2000, {
leading: false,
});
This will wait 2s Will execute the first function call

Step four : The function is executed for the last time
" throttle " It is only related to the interval of the function , It has nothing to do with the completion of the last character input .
So when the last character is input , If the time interval with the last function call does not reach the specified time interval , At this time, the function will not be executed . If it is necessary to carry out , You need custom parameters to control function execution .
Through parameters trailing The last execution of the control function , The default is false. When the function needs to be executed at the end , Set the timer before the execution of each time interval , Wait until the interval executes the function , Clear timer , If the last character has not reached the specified interval after input , Then execute the contents in the timer .
function throttle(fn, interval, options = {
}) {
let startTime = 0;
// Set a timer
let timer = null;
// leading The default value is true,trailing The default value is false
const {
leading = true, trailing = false } = options;
const _throttle = function (...args) {
let currentTime = new Date().getTime();
// When immediate execution is not required , Set the initial value to 0 Of startTime Change to current time
if (!leading && !startTime) {
startTime = currentTime;
}
let restTime = interval - (currentTime - startTime);
if (restTime <= 0) {
// When there is a timer , Clear timer
if (timer) {
clearTimeout(timer);
timer = null;
}
fn.apply(this, args);
startTime = currentTime;
// When the execution is completed, the following timer code will not be executed , Avoid repetition
return;
}
// If the last execution is required
if (trailing && !timer) {
// Set timer
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
// When immediate execution is required , The start time is assigned to the current time , conversely , The assignment is 0
startTime = !leading ? 0 : new Date().getTime();
}, restTime);
}
};
return _throttle;
}
// Pass in leading、trailing Parameters
inputEl.oninput = throttle(inputEvent, 2000, {
leading: false,
trailing: true,
});
At this point, the last character is entered , Wait for the interval set in the timer (restTime), The function will execute again .

Step five : Cancel the function
There may be such a scenario , When the user searches, he clicks cancel , Or close the page , At this point, there is no need to send requests .
We add a cancel button , Click to terminate the operation .
// html
<input />
<button> Cancel </button>
// javascript
function throttle(fn, interval, options = {
}) {
let startTime = 0;
// Set a timer
let timer = null;
// leading The default value is true,trailing The default value is false
const {
leading = true, trailing = false } = options;
const _throttle = function (...args) {
let currentTime = new Date().getTime();
// When immediate execution is not required , Set the initial value to 0 Of startTime Change to current time
if (!leading && !startTime) {
startTime = currentTime;
}
let restTime = interval - (currentTime - startTime);
if (restTime <= 0) {
// When there is a timer , Clear timer
if (timer) {
clearTimeout(timer);
timer = null;
}
fn.apply(this, args);
startTime = currentTime;
// When the execution is completed, the following timer code will not be executed , Avoid repetition
return;
}
// If the last execution is required
if (trailing && !timer) {
// Set timer
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
// When immediate execution is required , The start time is assigned to the current time , conversely , The assignment is 0
startTime = !leading ? 0 : new Date().getTime();
}, restTime);
}
};
// Define a cancellation method on the function object
_throttle.cancel = function () {
// When there is a timer , Empty
if (timer) {
clearTimeout(timer);
timer = null;
// Reset start time
startTime = 0;
}
};
return _throttle;
}
// obtain dom Elements
const inputEl = document.querySelector("input");
const cancelBtn = document.querySelector("button");
const _throttle = throttle(inputEvent, 2000, {
leading: false,
trailing: true,
});
// The binding event
inputEl.oninput = _throttle;
cancelBtn.onclick = _throttle.cancel;
When you click Cancel , The contents of the timer will no longer be executed

Step six : Function return value
above " throttle " After the function is executed, there is no return value , If you need to return a value , There are two forms .
Callback function
Pass the form of callback function in the parameter , To get the return value .
function throttle(fn, interval, options = {
}) {
let startTime = 0;
// Set a timer
let timer = null;
// leading The default value is true,trailing The default value is false, The incoming callback function is used to receive the return value
const {
leading = true, trailing = false, callbackFn } = options;
const _throttle = function (...args) {
let currentTime = new Date().getTime();
// When immediate execution is not required , Set the initial value to 0 Of startTime Change to current time
if (!leading && !startTime) {
startTime = currentTime;
}
let restTime = interval - (currentTime - startTime);
if (restTime <= 0) {
// When there is a timer , Clear timer
if (timer) {
clearTimeout(timer);
timer = null;
}
// Get the result of executing the function
const result = fn.apply(this, args);
// Execute the incoming callback function
if (callbackFn) callbackFn(result);
startTime = currentTime;
// When the execution is completed, the following timer code will not be executed , Avoid repetition
return;
}
if (trailing && !timer) {
timer = setTimeout(() => {
timer = null;
// Get the result of executing the function
const result = fn.apply(this, args);
// Execute the incoming callback function
if (callbackFn) callbackFn(result);
// When immediate execution is required , The start time is assigned to the current time , conversely , The assignment is 0
startTime = !leading ? 0 : new Date().getTime();
}, restTime);
}
};
// Define a cancellation method on the function object
_throttle.cancel = function () {
if (timer) {
// When there is a timer , Empty
clearTimeout(timer);
timer = null;
// Reset start time
startTime = 0;
}
};
return _throttle;
}
const inputEl = document.querySelector("input");
const cancelBtn = document.querySelector("button");
// The incoming callback function is used to receive the return value
const _throttle = throttle(inputEvent, 2000, {
leading: false,
trailing: true,
callbackFn: (value) => {
console.log(" Get the return value ", value);
},
});
inputEl.oninput = _throttle;
cancelBtn.onclick = _throttle.cancel;
Every time the response function is executed , The callback function will be executed once .

promise
By returning promise To get the return value
function throttle(fn, interval, options = {
}) {
let startTime = 0;
// Set a timer
let timer = null;
// leading The default value is true,trailing The default value is false
const {
leading = true, trailing = false } = options;
const _throttle = function (...args) {
// adopt promise To return results
return new Promise((resolve, reject) => {
let currentTime = new Date().getTime();
// When immediate execution is not required , Set the initial value to 0 Of startTime Change to current time
if (!leading && !startTime) {
startTime = currentTime;
}
let restTime = interval - (currentTime - startTime);
if (restTime <= 0) {
// When there is a timer , Clear timer
if (timer) {
clearTimeout(timer);
timer = null;
}
// Get the result of executing the function
const result = fn.apply(this, args);
// adopt resolve Return a successful response
resolve(result);
startTime = currentTime;
return;
}
if (trailing && !timer) {
timer = setTimeout(() => {
timer = null;
// Get the result of executing the function
const result = fn.apply(this, args);
// adopt resolve Return a successful response
resolve(result);
// When immediate execution is required , The start time is assigned to the current time , conversely , The assignment is 0
startTime = !leading ? 0 : new Date().getTime();
}, restTime);
}
});
};
// Define a cancellation method on the function object
_throttle.cancel = function () {
if (timer) {
// When there is a timer , Empty
clearTimeout(timer);
timer = null;
// Reset start time
startTime = 0;
}
};
return _throttle;
}
// obtain dom Elements
const inputEl = document.querySelector("input");
const cancelBtn = document.querySelector("button");
const _throttle = throttle(inputEvent, 2000, {
leading: false,
trailing: true,
});
// apply Is used to this Point to input Elements
const promiseCallback = function (...args) {
_throttle.apply(inputEl, args).then((res) => {
console.log("promise Callback ", res);
});
};
// The binding event
inputEl.oninput = promiseCallback;
cancelBtn.onclick = _throttle.cancel;
promise call then Method gets the return value

Use throttling function in development to optimize the performance of the project , You can customize as above , You can also use third-party libraries .
About anti shake function , You can refer to this article , Custom anti shake function five steps to deal with complex requirements
The above is related to the anti shake function , About js senior , There are many things that developers need to master , You can look at other blog posts I wrote , Ongoing update ~
边栏推荐
- Program analysis and Optimization - 9 appendix XLA buffer assignment
- Additional: token; (don't read until you finish writing...)
- 数据集-故障诊断:西储大学轴承的各项数据以及数据说明
- 流媒体技术优化
- C MVC creates a view to get rid of the influence of layout
- [shutter] shutter photo wall (center component | wrap component | clickrrect component | stack component | positioned component | button combination component)
- 带角度的检测框 | 校准的深度特征用于目标检测(附实现源码)
- Sourcetree details
- What experience is there only one test in the company? Listen to what they say
- Open source | Wenxin big model Ernie tiny lightweight technology, which is accurate and fast, and the effect is fully open
猜你喜欢

MySQL基础

67页新型智慧城市整体规划建设方案(附下载)

容器运行时分析

What if win11 can't turn off the sticky key? The sticky key is cancelled but it doesn't work. How to solve it

2022 latest and complete interview questions for software testing

How difficult is it to be high? AI rolls into the mathematics circle, and the accuracy rate of advanced mathematics examination is 81%!

Interface switching based on pyqt5 toolbar button -1

Markdown basic grammar

Integration of revolution and batch normalization

How to apply for company email when registering in company email format?
随机推荐
cocospods 的使用
Go basic data type
MFC 获取当前时间
Matlab 信号处理【问答笔记-1】
Bean加载控制
接口差异测试——Diffy工具
程序分析与优化 - 9 附录 XLA的缓冲区指派
判断二叉树是否为满二叉树
All things work together, and I will review oceanbase's practice in government and enterprise industry
[shutter] shutter open source project reference
基于OpenCV实现口罩识别
一文掌握基于深度学习的人脸表情识别开发(基于PaddlePaddle)
RTP 接发ps流工具改进(二)
Interface automation coverage statistics - used by Jacobo
【STL源码剖析】仿函数(待补充)
Remote connection of raspberry pie by VNC viewer
CADD course learning (4) -- obtaining proteins without crystal structure (Swiss model)
Wechat applet basic learning (wxss)
ArrayList analysis 2: pits in ITR, listiterator, and sublist
带角度的检测框 | 校准的深度特征用于目标检测(附实现源码)