各位大佬,前端按钮重复点击提交请求的最佳方法?

2019-09-05 10:18:12 +08:00
 LyleRockkk

目前我知道的有 3 种 1:按钮绑定一个变量绑定 disable,请求完成后改为 false (每个按钮都要加感觉有点蠢) 2:ajax 之前 全局加 loading 弹层, 防止重复点击(如果时间很短,loading 也影响体验) 3:Vue 中 弄个指令,给一个时间,该时间内只执行一次事件(这个时间感觉也不靠谱,太长太短都不好)

16845 次点击
所在节点    Vue.js
77 条回复
TomVista
2019-09-05 19:55:21 +08:00
我用的是异步函数自我同步。
用闭包保留一个状态,isDoing-true,回调或者 await 之后,改 isDoing-false,
这样,在执行队列中只能有一个该函数
RubyJack
2019-09-05 20:38:52 +08:00
幂等接口真是笑死我了,button 引入点击状态是真的难, 只能甩锅给后端了

加购物车这种场景, 谁来示范一下幂等?
redbuck
2019-09-05 21:36:37 +08:00
方案一改一改。

接口有统一封装就改请求函数,没有就劫持 ajax。
用链接和参数做 key,请求就标记,回来就干掉。
lihongjie0209
2019-09-05 21:40:14 +08:00
@RubyJack #62 有些人认为接口幂等很简单, 没办法
jss
2019-09-05 22:01:47 +08:00
就不能给按钮一个 loading ?
4DAX07B8Kle4Dm6T
2019-09-05 22:15:14 +08:00
表单令牌了解一下
wupher
2019-09-06 09:25:26 +08:00
抛开前端不提,后端也要防重放攻击啊。

人家不通过前端,直接跑个脚本发 http 请求攻击肿么办?
lihongjie0209
2019-09-06 09:52:01 +08:00
@wupher #67 攻击==表单重复提交??
wupher
2019-09-06 10:11:53 +08:00
@lihongjie0209 重放攻击是这样。如果你某个业务需要特别多的计算,而且结果无法实现幂等,那么攻击者可以通过录制请求或者伪造请求。大量发往服务器,实现攻击目的。
lihongjie0209
2019-09-06 10:28:03 +08:00
@wupher #69
用户提交表单的时候我们默认用户处于一个安全的状态, 比如登录,验证码, 表单签名。

攻击者处于我们系统的最外围, 要攻击必须先突破我们的安全限制才能进行下一步的动作。


你把表单重复提交这种安全域范围内的事情当作攻击, 就相当于你为了预防 1000KM 外的狙击手每天呆在地下堡垒
wupher
2019-09-06 11:17:36 +08:00
@lihongjie0209 这个看业务,看团队,看技术了。我相信表单和表单也不一样,对吧?

个人觉得,像支付宝付款那个表单,怎么防范都是应该的,对吧。

防重放我觉得其实也没你想的那么难,有很多简单的策略和实现就能初步实现。实现后通过诸如 AOP、API Gateway、Filter 都是简单配置一下即可。并不会对业务开发造成太高代价。
lihongjie0209
2019-09-06 11:32:18 +08:00
@wupher #71
重放不难防范, 但这个不是我们是使用一项技术的原因。一大堆简单的技术放在一起复杂度还是会大量的增加
lihongjie0209
2019-09-06 11:33:46 +08:00
@wupher #71 至于你说的某些特别重要的表单, 那么应该是针对几个表单的接口做安全处理, 而不是全局性的
RV0n
2019-09-06 13:57:01 +08:00
加锁
mazai
2019-09-06 14:30:37 +08:00
加个 loading 防护罩
source
2019-09-09 16:19:54 +08:00
前端这边可以写个工具方法,需要防重复提交的 api 用它包装一下(假如它返回一个 promise )
// mock api
function api(params) {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve(params), 5000)
});
}

// 生成带锁的 api
function lockApi(api) {
let lock = false
return (...params) => {
if (!lock) {
lock = true
return api(...params)
.then(data => {
lock = false
return data
})
} else {
return Promise.reject('too frequent!')
}
}
}
source
2019-09-09 16:21:13 +08:00
缩进炸了,贴张截图吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/598108

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX