博客地址:https://ainyi.com/79

日常浏览网页中,在进行窗口的 resize、scroll 或者重复点击某按钮发送请求,此时事件处理函数或者接口调用的频率若无限制,则会加重浏览器的负担,界面可能显示有误,服务端也可能出问题,导致用户体验非常糟糕

此时可以采用 debounce(防抖)和 throttle(节流)的方式来减少事件或接口的调用频率,同时又能实现预期效果

防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在 delay 时间后触发函数,但是在 delay 时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发

节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在连续触发的事件后才触发最后一次事件的函数

上面的解释,摘抄网上的解答

防抖

debounce:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时

如下图,持续触发 scroll 事件时,并不执行 handle 函数,当 1000ms 内没有触发 scroll 事件时,才会延时触发 scroll 事件

function debounce(fn, wait) {
let timeout = null
return function() {
if(timeout !== null) {
clearTimeout(timeout)
}
timeout = setTimeout(fn, wait)
}
}
// 处理函数
function handle() {
console.log('处理函数', Math.random())
} // 滚动事件
window.addEventListener('scroll', debounce(handle, 1000))

节流

throttle:当持续触发事件时,保证一定时间段内只调用一次事件处理函数

仔细了解了才知道,我以前刚学前端的时候,做 banner 图特效,两边的点击按钮如果一直重复点击就会出问题,后面摸索了此方法,原来这名字叫做节流

如下图,持续触发 scroll 事件时,并不立即执行 handle 函数,每隔 1000 毫秒才会执行一次 handle 函数

时间戳方法

let throttle = function(func, delay) {
let prev = Date.now()
return function() {
let context = this
let args = arguments
let now = Date.now()
if(now - prev >= delay) {
func.apply(context, args)
prev = Date.now()
}
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', throttle(handle, 1000))

定时器方法

let throttle = function(func, delay) {
let timer = null
return function() {
let context = this
let args = arguments
if(!timer) {
timer = setTimeout(function() {
func.apply(context, args)
timer = null
}, delay)
}
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', throttle(handle, 1000))

时间戳+定时器

let throttle = function(func, delay) {
let timer = null
let startTime = Date.now()
return function() {
let curTime = Date.now()
let remaining = delay - (curTime - startTime)
let context = this
let args = arguments
clearTimeout(timer)
if(remaining <= 0) {
func.apply(context, args)
startTime = Date.now()
} else {
timer = setTimeout(func, remaining)
}
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', throttle(handle, 1000))

每个请求必须发送的问题

如下图的购买页,操作发现一个购买明细的查价接口的频繁调用问题

如下图:

购买页改变任何一个选项,都会调用查价接口,然后右边会显示对应的价格。尤其是购买数量,这是一个数字选择器,如果用户频繁点击 + 号,就会连续调用多次查价接口,但最后一次的查价接口返回的数据才是最后选择的正确的价格

每个查价接口逐个请求完毕的时候,右边的显示价格也会逐个改变,最终变成最后正确的价格,一般来说,这是比较不友好的,用户点了多次后,不想看到价格在变化,尽管最终是正确的价格,但这个变化的过程是不能接受的

也不应该使用上面的防抖解决方式,不能设置过长的定时器,因为查价接口不能等太久,也不能设置过短的定时器,否则会出现上面说的问题(价格在变化)

所以这是一个每个请求必须发送,但是只显示最后一个接口返回的数据的问题

我这里采用入栈、取栈顶元素比对请求参数的方法解决:

// 查价
async getPrice() {
// 请求参数
const reqData = this.handleData()
// push 入栈
this.priceStack.push(reqData)
const { result } = await getProductPrice(reqData)
// 核心代码,取栈顶元素(最后请求的参数)比对
if(this.$lang.isEqual(this.$array.last(this.priceStack), reqData)) {
// TODO
// 展示价格代码...
}
}

注解,上述的 this.$lang.isEqual、this.$array.last 均是 lodash 插件提供的方法

注册到 Vue 中

import array from 'lodash/array'
import Lang from 'lodash/lang' Vue.prototype.$array = array
Vue.prototype.$lang = Lang

博客地址:https://ainyi.com/79

防抖与节流 & 若每个请求必须发送,如何平滑地获取最后一个接口返回的数据的更多相关文章

  1. 微信小程序POST请求参数传递不到后台, 前台获取不到后端返回的数据, 以及 post 请求返回 404 但后台能收到数据

    1 微信小程序POST请求参数传递不到后台 需要在微信请求 wx.request 改变默认 header 配置为如下 wx.request({ url: 'test.php', //仅为示例,并非真实 ...

  2. 【转载】jmeter将上一个接口返回值作为下一个接口的请求参数

    第一:通过JSON Extractor 插件来提取JSON响应结果 原文地址:http://blog.csdn.net/dreamtl/article/details/68957122 接口响应结果, ...

  3. jmeter将上一个接口返回值作为下一个接口的请求参数

    在jmeter中有时候会用到,将上一个接口的返回值作为下一个接口的请求参数 具体操作如下: 1.首先新建一个http请求(右键线程组--添加Sampler--http请求),同时添加好接口相应的请求参 ...

  4. 给AFNetworking添加请求缓存功能实现在没有网络的情况下返回缓存数据

    原理:先给NSURLSession地Configuration设置一个内存和本地代理,原来的网络请求结束后会查找缓存的代理字典,并执行代理对象对应的操作方法,需要做的就是拦截错误的方法,返回缓存的数据 ...

  5. 2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

    Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 ...

  6. 详谈js防抖和节流

    本文由小芭乐发表 0. 引入 首先举一个例子: 模拟在输入框输入后做ajax查询请求,没有加入防抖和节流的效果,这里附上完整可执行代码: <!DOCTYPE html> <html ...

  7. JS的防抖和节流

    数个月之前,在一次前端的性能优化中,接触到了JS中防抖和节流,一开始还不明白他们的应用在哪里,可后来才知道,这是前端中最基础的性能优化,在绑定 scroll .resize 这类事件时,当它发生时,它 ...

  8. 来聊聊JavaScript中的防抖和节流

    目录 JavaScript防抖和节流 问题还原 防抖 什么是防抖 使用场景 节流 什么是节流 使用场景 JavaScript防抖和节流 问题还原 我们先来通过代码把常见的问题还原: <html& ...

  9. React 实现input输入框的防抖和节流

    1.为什么使用防抖和节流对于频繁触发的事件 比如keydown keyup事件 当频繁点击时候 会多次触发事件 页面出现卡顿 影响性能 2.函数防抖(debounce):间隔时间内只执行一次   函数 ...

随机推荐

  1. 利用Python进行数据分析:【Matplotlib】

    一.简单介绍Matplotlib 1.Matplotlib是一个强大的Python绘图和数据可视化的工具包2.安装方法:pip install matplotlib 3.引用方法:import mat ...

  2. redis-分布式锁-消除竞争条件

    因为信号量的设计过程中,获取一个信号量需要执行多个命令组成的流水,这样容易形成竞争条件. 为了消除信号量实现中所有可能出现的竞争条件,构建一个正确的计数信号量,需要在 信号量时,添加带有短暂超时时间的 ...

  3. mybatis简单入门介绍

    mybatis入门 简介 什么是mybatis? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及 ...

  4. 性能测试的基础知识--QPS和TPS

    基本概念: QPS:Queries Per Second意思是“每秒查询率” ,是一台服务器每秒能够相应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准. TPS:Transa ...

  5. 【ASP.NET基础--MVC】MVC视图基础语法学习

    初步接触.net MVC的视图语法,很多东西都不太熟悉,感觉跟之前的aspx以及html都有一些区别,最近看别人的代码,一边看一边研究,现把学到的东西在这里记录一下,以便日后翻阅. 第一部分:基础知识 ...

  6. .net core 3.0 Signalr - 02 使用强类型的Hub

    ## 强类型的优缺点 - 优点 强类型的Hub可以避免魔法函数名,相比弱类型更容易维护和发现问题,直接上代码 - 缺点 特么的得多些好几行代码 ## 代码 ### 接口定义 ``` C# /// // ...

  7. Nginx负载均衡配置实例

    面对高并发的问题,企业往往会从两个方面来解决.其一,从硬件上面,提升硬件的配置,增加服务器的性能:另外,就是从软件上,将数据库和WEB服务器分离,使数据库和WEB服务器都能够充分发挥各自的性能,并且二 ...

  8. MongoDB 学习笔记之 $or与索引关系

    $or与索引关系: 对leftT集合的timestamp创建索引 执行$or语句:db.leftT.find({$or: [{ "timestamp" : 5},{"ag ...

  9. Django学习之文件下载

    在实际的项目中很多时候需要用到下载功能,如导excel.pdf或者文件下载,当然你可以使用web服务自己搭建可以用于下载的资源服务器,如nginx,这里我们主要介绍django中的文件下载. 我们这里 ...

  10. springboot项目目录结构

    idea新建springboot项目 按默认下一步至完成,默认目录结构如下 pom.xml文件内容如下 <?xml version="1.0" encoding=" ...