当前位置:网站首页>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 ~
边栏推荐
- 采用VNC Viewer方式遠程連接樹莓派
- Third party payment function test point [Hangzhou multi tester _ Wang Sir] [Hangzhou multi tester]
- 開源了 | 文心大模型ERNIE-Tiny輕量化技術,又准又快,效果全開
- JSON数据传递参数
- The privatization deployment of SaaS services is the most efficient | cloud efficiency engineer points north
- The privatization deployment of SaaS services is the most efficient | cloud efficiency engineer points north
- JDBC教程
- Go basic data type
- JDBC tutorial
- How does win11 turn on visual control? Win11 method of turning on visual control
猜你喜欢

Convolution和Batch normalization的融合

JDBC练习案例

【ML】李宏毅三:梯度下降&分类(高斯分布)

Data set - fault diagnosis: various data and data description of bearings of Western Reserve University

容器运行时分析

直击产业落地!飞桨重磅推出业界首个模型选型工具

Difference between NVIDIA n card and amda card

RuntimeError: no valid convolution algorithms available in CuDNN

Explain in detail the process of realizing Chinese text classification by CNN

What if win11 can't turn off the sticky key? The sticky key is cancelled but it doesn't work. How to solve it
随机推荐
直击产业落地!飞桨重磅推出业界首个模型选型工具
Ideal car × Oceanbase: when the new forces of car building meet the new forces of database
C MVC creates a view to get rid of the influence of layout
Additional: token; (don't read until you finish writing...)
How QT exports data to PDF files (qpdfwriter User Guide)
35 pages dangerous chemicals safety management platform solution 2022 Edition
2022 latest and complete interview questions for software testing
PHP get real IP
MFC文件操作
yolov5test. Py comment
leetcode 650. 2 Keys Keyboard 只有两个键的键盘(中等)
JDBC教程
The privatization deployment of SaaS services is the most efficient | cloud efficiency engineer points north
RTP 接发ps流工具改进(二)
Wechat applet basic learning (wxss)
Interface difference test - diffy tool
What if win11 can't turn off the sticky key? The sticky key is cancelled but it doesn't work. How to solve it
yolov5train. py
Returns the root node of the largest binary search subtree in a binary tree
Returns the maximum distance between two nodes of a binary tree