如何在 Vue 3 中使用 debounce 函数进行 axios 调用

问题描述 投票:0回答:3

我有使用 axios 从 PHP 脚本获取 JSON 数据的代码。目前,此调用是在输入字段的输入时触发的。

这很好,只是每次按键都会触发呼叫。我想将这个函数反跳大约半秒。

我尝试从我创建的另一个名为 debounce.js 的文件导入一个函数,其中包含:

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

我想将去抖动添加到此方法中:

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
    })
}

我想将这个去抖动函数包装在整个方法中,因为我想对整个方法进行去抖动,而不仅仅是检索数据部分。所以我尝试了这个:

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 }
}

但是我遇到这样的语法错误。如何为整个 fetchResults 方法正确实现此去抖?

这是我的整个 JS 代码,没有语法错误:

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
        }
    },
    computed: {
        // 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');
javascript vue.js axios debouncing
3个回答
4
投票

你没有说你有什么语法错误以及在哪里。

我找到了一个,看起来你想创建一个函数表达式。

文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function

问题是你的语法:

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

您不能使用

async
定义函数表达式,此外,您的
await
无效,因为它所在的函数没有
async

应该是:

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

2
投票

如果你不想使用任何额外的包,你可以像这样在 Vue 3 中使用 debounce。

<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);
    },
  },
  computed: {
    query: {
      get() {
        return this.query;
      },
      set(val) {
        this.fetchResults(val);
        this.query = val;
      },
    },
  },
});

0
投票

对于那些像我一样使用 Vue Composition Api 找到方法的人:

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

以任何你喜欢的方式添加lodash

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

调用你的函数

// 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>
© www.soinside.com 2019 - 2024. All rights reserved.