javascript - How can I use a debounce function for an axios call in Vue 3 - Stack Overflow

I've got code that gets JSON data from a PHP script using axios. Currently this call is triggered

I've got code that gets JSON data from a PHP script using axios. Currently this call is triggered on input of an input field.

This is fine except the call is triggered every key press. I would like to debounce this function for maybe half a second.

I've tried importing a function from another file that I created called debounce.js which contains:

const debounce = (fn, delay) => {
    let timeout
  
    return (...args) => {
      if (timeout) {
        clearTimeout(timeout)
      }
  
      timeout = setTimeout(() => {
        fn(...args)
      }, delay)
    }
  }
  
  export default debounce

I want to add the debounce to this method:

async fetchResults(){
    await axios.post('includes/searchproducts_json.php', {
        // Post data, add value of input to searchterm
        searchterm: this.$refs.searchterm.value
        
    })
    .then((response)=>{
        // Check if status is 200 (OK) and total_results is not 0
        // If true show results div and fill data
        if (response.status === 200 && response.data.total_results != 0) {
            this.showResultDiv = true
            this.results = response.data.results
            this.totalResults = response.data.total_results
            this.finishedCall = true
        }else{
            this.showResultDiv = false
        }
    })
    .catch((error)=>{
        console.log(error)
    })
    .then((response)=>{
        // Get length of returned object and add to results
        this.finishedCall = true
    })
}

I thought to wrap this debounce function around the entire method because I want to debounce the entire method, not just the retrieving data part. So I tried this:

setup(){
    async fetchResults = debounce(() => {
        await axios.post('includes/searchproducts_json.php', {
            // Post data, add value of input to searchterm
            searchterm: this.$refs.searchterm.value
            
        })
        .then((response)=>{
            // Check if status is 200 (OK) and total_results is not 0
            // If true show results div and fill data
            if (response.status === 200 && response.data.total_results != 0) {
                this.showResultDiv = true
                this.results = response.data.results
                this.totalResults = response.data.total_results
                this.finishedCall = true
            }else{
                this.showResultDiv = false
            }
        })
        .catch((error)=>{
            console.log(error)
        })
        .then((response)=>{
            // Get length of returned object and add to results
            this.finishedCall = true
        })

    }, 500)
    return { fetchResults }
}

But I get syntax errors like this. How can I correctly implement this debounce for the entire fetchResults method?

This is my entire JS code without the syntax errors:

import debounce from './assets/js/debounce.js'
let app = Vue.createApp({
    data: function(){
        return{
            // Object to fill with JSON response
            results:[],
            showResultDiv: false,
            totalResults: 0,
            finishedCall: false
        }
    },
    puted: {
        // Limit total results in searchdropdown to 6
        resultsToShow() {
            return this.results.slice(0, 6)
        },
        // Set the actual unlimited result amount to totalResults with matching string
        resultString(){
            if(this.totalResults == 1){
                return this.totalResults + ' resultaat'
            }else{
                return this.totalResults + ' resultaten'
            }
        }
    },
    methods:{
        // Function to show div with loading dots until json returned
        loadDiv(condition){
            this.showResultDiv = condition
        },
        async fetchResults(){
            await axios.post('includes/searchproducts_json.php', {
                // Post data, add value of input to searchterm
                searchterm: this.$refs.searchterm.value
                
            })
            .then((response)=>{
                // Check if status is 200 (OK) and total_results is not 0
                // If true show results div and fill data
                if (response.status === 200 && response.data.total_results != 0) {
                    this.showResultDiv = true
                    this.results = response.data.results
                    this.totalResults = response.data.total_results
                    this.finishedCall = true
                }else{
                    this.showResultDiv = false
                }
            })
            .catch((error)=>{
                console.log(error)
            })
            .then((response)=>{
                // Get length of returned object and add to results
                this.finishedCall = true
            })
        }
    }
})

app.mount('#v_search');

I've got code that gets JSON data from a PHP script using axios. Currently this call is triggered on input of an input field.

This is fine except the call is triggered every key press. I would like to debounce this function for maybe half a second.

I've tried importing a function from another file that I created called debounce.js which contains:

const debounce = (fn, delay) => {
    let timeout
  
    return (...args) => {
      if (timeout) {
        clearTimeout(timeout)
      }
  
      timeout = setTimeout(() => {
        fn(...args)
      }, delay)
    }
  }
  
  export default debounce

I want to add the debounce to this method:

async fetchResults(){
    await axios.post('includes/searchproducts_json.php', {
        // Post data, add value of input to searchterm
        searchterm: this.$refs.searchterm.value
        
    })
    .then((response)=>{
        // Check if status is 200 (OK) and total_results is not 0
        // If true show results div and fill data
        if (response.status === 200 && response.data.total_results != 0) {
            this.showResultDiv = true
            this.results = response.data.results
            this.totalResults = response.data.total_results
            this.finishedCall = true
        }else{
            this.showResultDiv = false
        }
    })
    .catch((error)=>{
        console.log(error)
    })
    .then((response)=>{
        // Get length of returned object and add to results
        this.finishedCall = true
    })
}

I thought to wrap this debounce function around the entire method because I want to debounce the entire method, not just the retrieving data part. So I tried this:

setup(){
    async fetchResults = debounce(() => {
        await axios.post('includes/searchproducts_json.php', {
            // Post data, add value of input to searchterm
            searchterm: this.$refs.searchterm.value
            
        })
        .then((response)=>{
            // Check if status is 200 (OK) and total_results is not 0
            // If true show results div and fill data
            if (response.status === 200 && response.data.total_results != 0) {
                this.showResultDiv = true
                this.results = response.data.results
                this.totalResults = response.data.total_results
                this.finishedCall = true
            }else{
                this.showResultDiv = false
            }
        })
        .catch((error)=>{
            console.log(error)
        })
        .then((response)=>{
            // Get length of returned object and add to results
            this.finishedCall = true
        })

    }, 500)
    return { fetchResults }
}

But I get syntax errors like this. How can I correctly implement this debounce for the entire fetchResults method?

This is my entire JS code without the syntax errors:

import debounce from './assets/js/debounce.js'
let app = Vue.createApp({
    data: function(){
        return{
            // Object to fill with JSON response
            results:[],
            showResultDiv: false,
            totalResults: 0,
            finishedCall: false
        }
    },
    puted: {
        // Limit total results in searchdropdown to 6
        resultsToShow() {
            return this.results.slice(0, 6)
        },
        // Set the actual unlimited result amount to totalResults with matching string
        resultString(){
            if(this.totalResults == 1){
                return this.totalResults + ' resultaat'
            }else{
                return this.totalResults + ' resultaten'
            }
        }
    },
    methods:{
        // Function to show div with loading dots until json returned
        loadDiv(condition){
            this.showResultDiv = condition
        },
        async fetchResults(){
            await axios.post('includes/searchproducts_json.php', {
                // Post data, add value of input to searchterm
                searchterm: this.$refs.searchterm.value
                
            })
            .then((response)=>{
                // Check if status is 200 (OK) and total_results is not 0
                // If true show results div and fill data
                if (response.status === 200 && response.data.total_results != 0) {
                    this.showResultDiv = true
                    this.results = response.data.results
                    this.totalResults = response.data.total_results
                    this.finishedCall = true
                }else{
                    this.showResultDiv = false
                }
            })
            .catch((error)=>{
                console.log(error)
            })
            .then((response)=>{
                // Get length of returned object and add to results
                this.finishedCall = true
            })
        }
    }
})

app.mount('#v_search');
Share Improve this question asked Feb 2, 2022 at 10:41 twantwan 2,65912 gold badges42 silver badges115 bronze badges 1
  • the lodash.debounce package might be useful, so you don't have to recreate the debounce function: npmjs./package/lodash.debounce – Xavier B. Commented Feb 2, 2022 at 11:20
Add a ment  | 

3 Answers 3

Reset to default 4

You didn't say what syntax error you are having and where.

I found one though and it seems like you are wanting to create a function expression.

Docs: https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Operators/function

The problem is your syntax:

setup(){
    async fetchResults = debounce(() => {
        await axios.post('includes/searchproducts_json.php', {

You can't define a function expression with async and besides, your await is invalid because the function it lives in doesn't have an async.

It should be:

setup() {
  const fetchResults = debounce(async () => {
    await axios.post('')

You can use debounce in Vue 3 like this if you don't want to use any additional packages.

<input type="search" v-model="query" />
const app = Vue.createApp({
  data() {
    return {
      query: "",
      results: [],
    };
  },
  methods: {
    debounce(func, timeout = 300) {
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(this, args);
        }, timeout);
      };
    },
    fetchResults(query) {
      this.debounce(async () => {
        await axios
          .post("includes/searchproducts_json.php", {
            searchterm: query,
          })
          .then((response) => {
            if (response.status === 200 && response.data.total_results != 0) {
              this.showResultDiv = true;
              this.results = response.data.results;
              this.totalResults = response.data.total_results;
              this.finishedCall = true;
            } else {
              this.showResultDiv = false;
            }
          })
          .catch((error) => {
            console.error(error);
          })
          .finally(() => {
            this.finishedCall = true;
          });
      }, 500);
    },
  },
  puted: {
    query: {
      get() {
        return this.query;
      },
      set(val) {
        this.fetchResults(val);
        this.query = val;
      },
    },
  },
});

For those who find their way here like me using Vue Composition Api:

<input @input="debounceSearch" v-model="searchstring">

Add lodash in whatever way you like

// bootstrap.js
window._ = require('lodash'); // option1
// yourFile.vue
<script setup>
import _ from 'lodash'                 // option2
import debounce from 'lodash/debounce' // option3

Call your function

// yourFile.vue
// for option 1 & 2
const debounceSearch = _.debounce(() => {fetchResults();}, 400)

// For option 3
const debounceSearch = debounce(() => {fetchResults();}, 400)

const fetchResults = () => {
  // run your axios.post(url, data) code here
}
</script>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742284421a4415069.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信