当前位置:网站首页>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 ~
边栏推荐
- 35页危化品安全管理平台解决方案2022版
- 接口自动化覆盖率统计——Jacoco使用
- 1380. Lucky numbers in the matrix
- Many to one, one to many processing
- JDBC练习案例
- 【OJ】两个数组的交集(set、哈希映射 ...)
- In February 2022, the ranking list of domestic databases: oceanbase regained its popularity with "three consecutive increases", and gaussdb is expected to achieve the largest increase this month
- Ideal car × Oceanbase: when the new forces of car building meet the new forces of database
- [analysis of STL source code] imitation function (to be supplemented)
- How does win11 turn on visual control? Win11 method of turning on visual control
猜你喜欢
67 page overall planning and construction plan for a new smart city (download attached)
MATLAB signal processing [Q & a notes-1]
程序分析与优化 - 9 附录 XLA的缓冲区指派
Digital collection trading website domestic digital collection trading platform
Implementation of VGA protocol based on FPGA
Bean加载控制
How can cross-border e-commerce achieve low-cost and steady growth by laying a good data base
Use redis to realize self increment serial number
开源了 | 文心大模型ERNIE-Tiny轻量化技术,又准又快,效果全开
Interface difference test - diffy tool
随机推荐
Open Source | Wenxin Big Model Ernie Tiny Lightweight Technology, Accurate and Fast, full Open Effect
来自数砖大佬的 130页 PPT 深入介绍 Apache Spark 3.2 & 3.3 新功能
JSON data transfer parameters
附加:token;(没写完,别看…)
MATLAB signal processing [Q & a notes-1]
Agnosticism and practice makes perfect
Matlab 信号处理【问答笔记-1】
yolov5detect. Py comment
leetcode 650. 2 Keys Keyboard 只有两个键的键盘(中等)
请求与响应
67页新型智慧城市整体规划建设方案(附下载)
实用系列丨免费可商用视频素材库
MFC文件操作
采用VNC Viewer方式远程连接树莓派
@How to use bindsinstance in dagger2
Container runtime analysis
2022 latest and complete interview questions for software testing
Solution: exceptiole 'xxxxx QRTZ_ Locks' doesn't exist and MySQL's my CNF file append lower_ case_ table_ Error message after names startup
Program analysis and Optimization - 9 appendix XLA buffer assignment
接口差异测试——Diffy工具