-
Notifications
You must be signed in to change notification settings - Fork 890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Day103:多个 tab 只对应一个内容框,点击每个 tab 都会请求接口并渲染到内容框,怎么确保频繁点击 tab 但能够确保数据正常显示? #916
Comments
一、分析因为每个请求处理时长不一致,可能会导致先发送的请求后响应,即请求响应顺序和请求发送顺序不一致,从而导致数据显示不正确。 即可以理解为连续触发多个请求,如何保证请求响应顺序和请求发送顺序一致。对于问题所在场景,用户只关心最后数据是否显示正确,即可以简化为:连续触发多个请求,如何保证最后响应的结果是最后发送的请求(不关注之前的请求是否发送或者响应成功) 类似场景:input输入框即时搜索,表格快速切换页码 二、解决方案防抖(过滤掉一些非必要的请求) + 取消上次未完成的请求(保证最后一次请求的响应顺序) 取消请求方法:
伪代码(以 setTimeout 模拟请求,clearTimeout 取消请求) /**
* 函数防抖,一定时间内连续触发事件只执行一次
* @param {*} func 需要防抖的函数
* @param {*} delay 防抖延迟
* @param {*} immediate 是否立即执行,为true表示连续触发时立即执行,即执行第一次,为false表示连续触发后delay ms后执行一次
*/
let debounce = function(func, delay = 100, immediate = false) {
let timeoutId, last, context, args, result
function later() {
const interval = Date.now() - last
if (interval < delay && interval >= 0) {
timeoutId = setTimeout(later, delay - interval)
} else {
timeoutId = null
if (!immediate) {
result = func.apply(context, args)
context = args = null
}
}
}
return function() {
context = this
args = arguments
last = Date.now()
if (immediate && !timeoutId) {
result = func.apply(context, args)
context = args = null // 解除引用
}
if (!timeoutId) {
timeoutId = setTimeout(later, delay)
}
return result
}
}
let flag = false // 标志位,表示当前是否正在请求数据
let xhr = null
let request = (i) => {
if (flag) {
clearTimeout(xhr)
console.log(`取消第${i - 1}次请求`)
}
flag = true
console.log(`开始第${i}次请求`)
xhr = setTimeout(() => {
console.log(`请求${i}响应成功`)
flag = false
}, Math.random() * 200)
}
let fetchData = debounce(request, 50) // 防抖
// 模拟连续触发的请求
let count = 1
let getData = () => {
setTimeout(() => {
fetchData(count)
count++
if (count < 11) {
getData()
}
}, Math.random() * 200)
}
getData()
/* 某次测试输出:
开始第2次请求
请求2响应成功
开始第3次请求
取消第3次请求
开始第4次请求
请求4响应成功
开始第5次请求
请求5响应成功
开始第8次请求
取消第8次请求
开始第9次请求
请求9响应成功
开始第10次请求
请求10响应成功
*/ |
确保频繁点击tab能够正常显示数据的关键是避免过多不必要的网络请求和渲染。 以下是一些可能有用的建议: 1.缓存结果:每次请求数据时,可以将结果存储在本地缓存中,这样就不需要每次都向服务器请求数据,并且可以快速渲染已经获得的数据。 2.减少请求:可以在用户点击tab时添加一个延迟器(debouncer),这个延迟器可以在用户点击tab后暂停一小段时间(如 200ms),以防止用户频繁点击产生太多的请求。 3.管理请求:可以使用RxJS这样的库来管理请求。RxJS使得请求管理更加方便,以便用户无需过多考虑每个请求的完成时间。通过使用RxJS,可以避免重复请求并保存最新的请求结果。 4.优化渲染:可以使用虚拟滚动(virtual scrolling)来优化渲染。虚拟滚动可以只渲染用户实际所需的内容,而不是渲染整个列表。 针对复杂业务建模:对于更复杂的业务,可以使用状态机来管理状态。状态机可以在不同的状态之间进行切换,并且每个状态只有一组特定的操作序列。例如,当一个 tab 被点击时,可以将状态机从“等待”状态转换为“请求”状态,然后再转换到“成功”或“失败”状态。 总之,为了确保频繁点击tab时数据正常显示,需要综合运用以上建议,例如使用本地缓存、减少请求,使用RxJS来管理请求等方式来进行优化,以实现更流畅的用户体验。 |
扫描下方二维码,收藏关注,及时获取答案以及详细解析,同时可解锁800+道前端面试题。
The text was updated successfully, but these errors were encountered: