Andreas Hunter
Andreas Hunter

Reputation: 5014

How to use settimeout with vue.js watchers?

I have custom watcher for search field in my application:

watch: {
  search (query) {
    if(query.length > 2) {
      axios.post(url, query)
        .then(res => {
          console.log(res)
        })
        .catch(error => {
          console.log(error)
        })
    }
  }
}

Here as you see I've send request to server on everey change value of search var in my case. I tired paste my code inside setTimeout but when user typing 3 time then requests too sent 3 times instead of one time. I need to wait when user is typing and after stop typing send one request to server.

setTimeout(function () { 
    // request code here
}, 3000);

How I can do it correctly inside vue.js watchers?

Upvotes: 1

Views: 6706

Answers (3)

ittus
ittus

Reputation: 22403

You can use debounce in lodash. It's perfect for your usecase.

import _ from lodash

watch: {
    search (query) {
        this.performSearch(query)
    }
},
methods: {
    performSearch: _.debounce(function(query) {
        axios.post(url, query)
        .then(res => {
          console.log(res)
        })
        .catch(error => {
          console.log(error)
        })
    }, 200)
}

If you want to implement it without lodash library, you can try

data() {
    return {
        timeoutQuery: null
    }
},
watch: {
    search (query) {
        if (this.timeoutQuery) { clearTimeout(this.timeoutQuery) }
        this.timeoutQuery = setTimeout(() => this.performSearch(query), 300)
    }
},
methods: {
    performSearch(query) {
        axios.post(url, query)
        .then(res => {
          console.log(res)
        })
        .catch(error => {
          console.log(error)
        })
    }
}

Upvotes: 6

ibnɘꟻ
ibnɘꟻ

Reputation: 900

You can use the arrow function and put your code inside of it.

data() {
  return {
    query: "",
    queryTimeout: null
  };
},
watch: {
  query(newValue, oldValue) {
    console.log(newValue, oldValue);
    const timer = 500;  // In miliseconds
    if (this.queryTimeout) {
      clearTimeout(this.queryTimeout);
    }
    setTimeout(() => {
      this.fetchData(newValue)
    }, timer);
  }
},
methods: {
  fetchData(query = null) {
    console.log(query);
    // Put your logic code here
  }
}

For more way to solve this problem, check this link. https://stackoverflow.com/a/38431406/4494207

Upvotes: 0

Christian Carrillo
Christian Carrillo

Reputation: 2761

You should use any flag to indicate than your request is busy:

    data () {
        return {
          isRequestBusy: false
        }
      },
    watch: {
      search (query) {
        if(query.length > 2 && !this.isRequestBusy) {
            this.isRequestBusy = true
            axios.post(url, query)
              .then(res => {
                console.log(res)
              })
              .catch(error => {
                console.log(error)
              })
              .finally(() => {
                this.isRequestBusy = false
              })
          }
        }
      }

Upvotes: 0

Related Questions