关于定时器(setinterval)和lodash的debounce搭配使用出现的奇怪问题?

前提:
页面有一个select和一个input,当这个两个元素的值发生变化时,需要调用ajax函数getDatas去后端获取数据。

需求如下:
1、页面首次加载调用getDatas函数获取数据,然后每隔 60s 自动调用该函数获取一次数据;
2、当页面select或者input发生变化时,立马调用同一ajax函数更新页面数据,并且此操作60s后,才自动调用getDatas函数

解决思路:
1、定义变量timer,利用定时器setinterval来定时执行(60s执行一次);
1、针对输入框的keyup事件,利用lodashdebounce方法过滤掉密集输入。当然keyup事件触发的时候,设置timer=60——手动获取后60s才自动获取

代码如下:

<template>
  <div>
      <select @change="changeType">
          <option value="11">1111</option>
          <option value="22">2222</option>
          <option value="33">3333</option>
      </select>
      <input type="text" @keyup="changeStr">
  </div>
</template>

<script>
import _ from 'lodash'

export default {
  data(){
      return{
          timer: 0
      }
  },
  methods:{
      changeType(){
          this.timer = 60;
          this.getDatas();
      },
      changeStr(){
        this.timer = 60;//当输入框触发keyup事件,确保60s后才自动调用getDatas函数
        var self = this;
        _.debounce(self.getDatas, 2, {//用户输连续入完成之后,才调用getDatas函数
            // 'leading': false,//指定调用在延迟开始前
            'trailing': true, //指定调用在延迟结束后
        })
      },
      getDatas(){
          console.log('获取数据123')
      }
  },
  mounted(){
    this.timer = -1;//首次设置小于0,立马调用getDatas函数
    setInterval(() => {
      this.timer--;
      console.log(this.timer)
      if(this.timer > 0){
      }else{
        this.getDatas();//调用getDatas函数
        this.timer = 60;//重置变量,60s后才能调用getDatas函数
      }
    },1000)
  }
}
</script>

问题如下:
1、inputkeyup事件触发,但是并没有执行getDatas函数;
2、当操作select和修改input的值后,发现好像有几个定时器在并行执行,截图如下:
图片描述

注:从图片中可以看到,有4、5个定时器在同时执行(图片中的4、5个数字分组后,他们是一次递减的,尽管顺序不规律),请问这两个问题的主要原因在哪儿呢??

麻烦高手指点,或者给出意见或建议,感谢!

补充:第一个问题我大概知道怎么回事了,因为每次触发keyup都是不停的调用 debounce 包装对象,并不是利用 debounce 包装keyup,但是该如何修改呢?

阅读 18k
2 个回答
<template>
  <div>
    <select @change="changeType">
      <option value="11">1111</option>
      <option value="22">2222</option>
      <option value="33">3333</option>
    </select>
    <input type="text" @keyup="changeStr">
  </div>
</template>

<script>

  export default {
    data() {
      return {
        changeTime: new Date().getTime(),
        interval: null
      }
    },
    methods: {
      changeType() {
        this.handleTimeout()
      },
      changeStr() {
        this.handleTimeout()
      },
      handleTimeout() {
        this.changeTime = new Date().getTime()
        setTimeout(() => {
          if (new Date().getTime() - this.changeTime >= 500) {
            this.getDatas()
            this.handleInterval()
          }
        }, 500)
      },
      handleInterval() {
        clearInterval(this.interval)
        this.interval = setInterval(() => {
          this.getDatas()
        }, 60000)
      },
      getDatas() {
        console.log('获取数据123')
      }
    },
    mounted() {
      this.getDatas()
      this.handleInterval()
    }
  }
</script>

改造了一下,应该好理解吧~

<template>
  <div>
      <select @change="changeType">
          <option value="11">1111</option>
          <option value="22">2222</option>
          <option value="33">3333</option>
      </select>
      <input type="text" v-model="str">
  </div>
</template>

<script>
import _ from 'lodash'

let timer = null    //计时器
let interval = 60000    //计时间隔
export default{
   data(){
      return{
        str: ''
      }
  },
  methods:{
      resetTimer(){
          clearInterval(timer)
          timer = setInterval(this.getDatas, interval)
      },
      changeType(){
          this.getDatas()
      },
      changeStr(){
          this.getDatas()
      },
      getDatas(){
          console.log('获取数据123')
          this.resetTimer()
      }
  },
  mounted(){
      this.getDatas()
      this.changeStr = _.debounce(this.changeStr, 500)
  },
  watch: {
      str (newStr) {
          this.changeStr()
      }
  }
}
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题