比如,不停点"下一页",不停点"前1小时",不停的点"升序降序"。
我希望用户点后只触发一次,等Ajax请求结束了才能再点,或者隔一段时间才允许再点。
当然,我看到了部分项目正在用的方法
- 点一下按钮,按钮变禁用
- 设置一个JS全局变量,某方法每调一次都会检查和该方法上次运行时间的间隔
- 触发一个屏幕遮罩,用户的点击被透明的DIV墙挡住
我不想为每个需要用到的地方写特例,那样业务代码太多了点。
有没有现成的...设计模式?或是什么方法
比如,不停点"下一页",不停点"前1小时",不停的点"升序降序"。
我希望用户点后只触发一次,等Ajax请求结束了才能再点,或者隔一段时间才允许再点。
当然,我看到了部分项目正在用的方法
我不想为每个需要用到的地方写特例,那样业务代码太多了点。
有没有现成的...设计模式?或是什么方法
我目前的做法是把ajax或者axios封装一下,然后加入loading。
这样每次请求前都会弹出loading,等请求回调回来loading消失。
伪代码,以axios为例
//请求拦截器
service.interceptors.request.use(
config => {
showLoading()
return config
},
error => {
hideLoading()
return Promise.reject(error)
}
)
//响应拦截器
service.interceptors.response.use(
response => {
hideLoading()
return response
},
error => {
hideLoading()
return Promise.reject(error)
}
)
看到有建议加 loading 的,其实是实现了一个简单的状态机:
如果是这种简单的场景用一个变量没什么问题,但如果有更加复杂的状态,比如:
就必须要有状态机的意识,才好控制复杂度,也可以借助 xstate/robot 这类第三方库。
从你的问题来看,其实你问题的核心不是解决重复点,而是解决重复提交的问题。
你前面自己提到的其实都是从解决重复点出发的方法,而且都是有效的方法,边城提到的有一定解决重复提交。
这个其实根本的有这样一些思路:
加个loading加载,看起来效果会好一点,也可以解决Ajax请求结束了才能再点,,,和按钮变禁用原原理是一样的,不过感觉loading效果要比按钮禁用要好的多,,,,大部分像表格上一页下页面一般也都加loading吧
这实际上是一个很有意思的问题,并且值得我们去开发一个通用的“好方法”来解决这类问题。
可以参照节流函数的写法,写一个“异步节流”,在上一个任务尚未结束前,对下一任务的请求直接拒绝:
const asyncThrottle = fn => {
let lock = false;
return function(...args){
return new Promise((resolve, reject) => {
if(lock) reject('asyncThrottle: 上一任务进行中');
lock = true;
fn.apply(this, args).then(res => {
lock = false;
resolve(res);
}).catch((err) => {
lock = false;
reject(err);
});
});
}
}
使用的代价就是需要把涉及的函数的返回值写成 thenable 风格。
如果这都算特例的话,我的建议是从更底层的地方做起。如果你用了 axios
,那么写一个拦截器,为每一个 API 创建一个请求状态字,调用某一个 API 的时候,先检查该 API 的状态,如果是 PENDING ,那就不发起请求。但是这样做是有风险的,因为一个 API 可以被多个地方调用,拦截器可能无法分辨。
10 回答11.7k 阅读
2 回答3.2k 阅读✓ 已解决
4 回答2.2k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
3 回答830 阅读✓ 已解决
3 回答1k 阅读✓ 已解决
2 回答1.2k 阅读✓ 已解决
给按钮一个事件 onClick ,可以用 async 和 await 配合,等待请求完毕也就是 onClick 绑定的事件执行完毕,才能再次点击。 这样即可以代码公用,而且防止多次点击触发。
例如:

使用方式:
