• 优雅解决按钮”重复点击“问题


    一、这个问题怎么解决呢?

    简单点,使用一个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)。

    https://www.houdianzi.com/xalogo/ 西安logo设计

    三、使用实例

    自动解锁使用例子:

    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。

  • 相关阅读:
    import 本地Python module或package
    JSON+YAML初步学习+ciscoconfparse
    Ansible用于网络设备管理 part 4 使用NAPALM成品库+Gabriele的方法+循环
    Community Value再理解
    职业素养-8S
    JavaWeb项目的数据库访问简单基础类
    FastJson+Servlet实现Ajax案例
    Echarts和JSTL、EL标签的混合使用
    大数据典型应用场景
    Web前端开发与设计13-购物车案例
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/14973924.html
Copyright © 2020-2023  润新知