简体   繁体   中英

Vuejs & Axios make multiple get requests

I have a simple Vue script, learning Vue for the first time:

 <!DOCTYPE html> <html> <head> <title>My first Vue app</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> </head> <body> <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question" type="text"> <img v-bind:src="image"> </p> <p>{{ answer }}</p> </div> <script> let watchExample = new Vue({ // Root element of app el : '#watch-example', // Properties keep track of data : { question : '', answer : 'I cannot give you an answer until you ask a question!', image : '', }, watch : { question : function(newVal, oldVal) { const vm = this; vm.answer = 'Waitinng for you to stop typing.'; setTimeout(function() { vm.getAnswer(); }, 350); } }, // App methods methods : { getAnswer: function() { const vm = this; if(!vm.question.includes('?')) { vm.answer = 'Questions usually contain a question mark'; vm.image = ''; return; } vm.answer = 'Thinking...'; setTimeout(function() { axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = response.data.answer; vm.image = response.data.image; }); }, 500); } } }); </script> </body> </html>

I noticed that when I type a question, containing a question mark( ? ) too fast, it makes multiple requests, and I get multiple responses. It clears out images upon multiple returned responses and adds new ones. If I type a question slowly, only one response is returned.

console.log(response) shows the multiple responses in the console.

How can I make only one request to get one response to a question no matter the typing speed?

What you need here is debounce from lodash

A good example was given in the Vue documentation

Pay attention to this particular code, as an example:

created: function () {
    // _.debounce is a function provided by lodash to limit how
    // often a particularly expensive operation can be run.
    // In this case, we want to limit how often we access
    // yesno.wtf/api, waiting until the user has completely
    // finished typing before making the ajax request. To learn
    // more about the _.debounce function (and its cousin
    // _.throttle), visit: https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },

Currently your are just delaying your call by wrapping it in a setTimeout. I think you're trying to accomplish a debounce effect.

Lodash has this function but if you don't already use lodash and don't want to include it in your project you could easily write it yourself in a few lines of code.

You could just restart the timer on every change (ie, stop the current timer if any, and then start another timer). Note that setTimeout() returns its associated timer ID, which you could pass to clearTimeout() to stop the timer. Your code should look similar to this:

watch: {
    question : function(newVal, oldVal) {
        ...

        clearTimeout(this._timerId);
        this._timerId = setTimeout(function() {
            vm.getAnswer();
        }, 350);
    }
},

 <!DOCTYPE html> <html> <head> <title>My first Vue app</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> </head> <body> <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question" type="text"> <img v-bind:src="image"> </p> <p>{{ answer }}</p> </div> <script> let watchExample = new Vue({ // Root element of app el : '#watch-example', // Properties keep track of data : { question : '', answer : 'I cannot give you an answer until you ask a question!', image : '', }, watch : { question : function(newVal, oldVal) { const vm = this; vm.answer = 'Waitinng for you to stop typing.'; clearTimeout(this._timerId); this._timerId = setTimeout(function() { vm.getAnswer(); }, 350); } }, // App methods methods : { getAnswer: function() { const vm = this; if(!vm.question.includes('?')) { vm.answer = 'Questions usually contain a question mark'; vm.image = ''; return; } vm.answer = 'Thinking...'; setTimeout(function() { axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = response.data.answer; vm.image = response.data.image; }); }, 500); } } }); </script> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM