tomatito
tomatito

Reputation: 411

How to delay @keyup handler in Vue.js

my view:

ns-input#filterName(type="text", v-model="filterName", @keyup="searchTimeOut()")

in my vue code:

getUsers() {
   .
   .
   .
   API.users.index(params).then(blabla);
   .
   .
   .
},

searchTimeOut() {
  let timeout = null;
  clearTimeout(timeout);
  // Make a new timeout set to go off in 800ms
  timeout = setTimeout(() => {
    this.getUsers();
    console.log("hi")
  }, 800);
},

I want call getUsers() only once after i stop typing and 800 ms. Right now, i'm calling getUsers() every time i write a letter.

Upvotes: 18

Views: 28233

Answers (2)

Mohammad Amin Lotfi
Mohammad Amin Lotfi

Reputation: 121

There is a better solution!

Debouncing is a technique to frequently restrict the calling of a time-consuming function, by delaying the execution of the function until a specified time to avoid unnecessary CPU cycles, and API calls and improve performance.

You can visit this site for a visual representation of this technique in JS

To implement debounce:

  1. In helper.js from utilities directory export debounce function
// utilities/helper.js
export const debounce = (func, delay = 600, immediate = false) => {
  let timeout
  return function () {
    const context = this
    const args = arguments
    const later = function () {
      timeout = null
      if (!immediate) func.apply(context, args)
    }
    const callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, delay)
    if (callNow) func.apply(context, args)
  }
}
  1. In your component you must import debounce function and assign it to the variable. I will do the assignment in mounted().
<script>
import { debounce } from '~/utilities/helper'

export default {
  name: 'MyComponent',
  data() {
    return {
      debounceFn: null,
      filterName: ''
    }
  },
  mounted() {
    this.debounceFn = debounce(() => this.getUsers(), 800)
  },
  methods: {
    onKeyup() {
      this.debounceFn()
    },
    getUsers() {
      // Logic
    }
  }
}
</script>
  1. Now connect script to the DOM
<template>
  <input type="text" v-model="filterName" @keyup="onKeyup" />
</template>

As a result, by doing the above steps, getUsers() only call once after you stop typing with an 800ms delay.

Upvotes: 7

oniondomes
oniondomes

Reputation: 2063

You drop this.timer value before clearing the interval. Do this instead:

searchTimeOut() {  
    if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
    }
    this.timer = setTimeout(() => {
        // your code
    }, 800);
}

Upvotes: 53

Related Questions