一、对思否的一点吐槽
思否上的许多按钮都没有做反复点击检测的问题,往往导致点击没反馈,屡次点击后忽然发表多条雷同内容,比方和一位同学的私信:
又如一个问题下的评论:
这个问题怎么解决呢?
简略点,应用一个 lock 标记,在申请收回时上锁,上锁后就不能够再发申请,能够在申请完结后解锁:
let clickButton = (function () {
let lock = false
return function (postParams) {if (lock) return
lock = true
// 假如应用 axios 发送申请
axios.post('urlxxx', postParams).then(// 表单提交胜利).catch(error => {
// 表单提交出错
console.log(error)
}).finally(() => {
// 不论成功失败 都解锁
lock = false
})
}
})()
button.addEventListener('click', clickButton)
当然对于 button 按钮,能够应用 setAttribute(‘disabled’, xxx) 和 removeAttribute(‘disabled’) 来代替 lock 标记。
这个计划问题在于,对于每一次按钮点击,咱们都要写个 lock 标记,相当于反复的逻辑会呈现在代码的各个中央——是不是能够封装一下呢?
二、封装按钮锁定、解锁逻辑
写一个装璜器将逻辑封装起来:
function ignoreMultiClick(func, manual = false) {
let lock = false
return function (...args) {if (lock) return
lock = true
let done = () => (lock = false)
if (manual) return func.call(this, ...args, done)
let promise = func.call(this, ...args)
Promise.resolve(promise).finally(done)
return promise
}
}
将想监听点击回调函数 func 作为传递给 ignoreMultiClick 进行装璜,会返回一个新的函数,应用该函数作为点击的回调事件即可。
这里同样用了一个标记 lock 来上锁,有两种办法解锁:
- 手动解锁:能够给 ignoreMultiClick 传递一个参数 manual,意思是被动调用解锁。若该参数为 truthy,则点击事件触发时会给原始的点击回调 func 传递一个参数 done,done 是一个函数,调用它能够解锁。
- 主动解锁:能够使原监听函数 func 返回一个 promise,在该 promise 决定后主动执行解锁操作。因为 Promise 治理回调函数十分不便,并且像 axios 这样十分罕用的申请库返回值自身也是一个 promise,所以默认状况应用这种形式。当然返回 promise 并不是必须的,有时候咱们在发申请前会进行一些验证,验证没通过则间接 return,此时装璜器函数也能失常解决,因为应用 Promise.resolve 包裹了一下 promise:
Promise.resolve(promise).finally(done)
。
三、应用实例
主动解锁应用例子:
let clickButton = ignoreMultiClick(function (postParams) {if (!checkForm()) return // 假如有一些检测表单的操作,查看不通过则间接返回
// 返回 promise
return axios.post('urlxxx', postParams).then(// 表单提交胜利).catch(error => {
// 表单提交出错
console.log(error)
})
})
button.addEventListener('click', clickButton)
手动解锁:
let clickButton = ignoreMultiClick(function (postParams, done) {if (!checkForm()) return done() // 表单验证不通过解锁
axios.post('urlxxx', postParams).then(// 表单提交胜利).catch(error => {
// 表单提交出错
console.log(error)
}).finally(() => done()) // 申请完结解锁
})
button.addEventListener('click', clickButton)
一般场景下还是主动解锁比较简单,因为可能有多个条件分支,手动解锁须要在每一个返回的中央都调用 done。