4

I have a vue.js application, I'm integrating a 3rd party payment provider support. The way it works is the UI sends a payment request to the backend, the backend processes it, sends a request to the PSP, and gets back a redirect url. The frontend then needs to redirect to this url where the user authenticates with the PSP.

Since the communication with the PSP is handled asynchronously on the backend, and I don't have two-way communication from backend to frontend, my frontend essentially needs to continuously poll the backend, asking "Do we have a redirect url yet?" over and over again.

My first naive approach was to display a component (through v-if, when the "intitialize payment" request returns OK) and in the component I have this:

 mounted() {
        setInterval(this.pollForRedirect, 1000);
    }

I did this so I could proceed with development, but it seems rather crude. Is there a best practice way to do this? Perhaps something native to vue?

Should I be periodically increasing the polling interval, so that I'm not spamming the server if the processing is taking longer than expected? How do I stop the polling when the user gives up and navigates away form the component?

Shaggydog
  • 3,456
  • 7
  • 33
  • 50

2 Answers2

8

Found this solution on reddit which worked for me:

data() {
    return {
        status: null,
        pollInterval: null
    }
},
    
    ...

methods() {
    fetchData() {
        axios.get('r/http://api/process/status')
            .then((response) => {
                //check if status is completed, if it is stop polling 
                if (response.data.status = 'completed') {
                    clearInterval(this.pollInterval) //won't be polled anymore 
                }
                this.status = response;
            });
    }
},

mounted() {
    this.fetchData()
    //check if the status is completed, if not fetch data every 10minutes.     
    if (this.status.status != 'completed') {
        this.pollInterval = setInterval(this.fetchData(), 600000) //save reference to the interval
        setTimeout(() => { clearInterval(this.pollInterval) }, 36000000) //stop polling after an hour
    }
}
andy
  • 253
  • 1
  • 3
  • 10
4

I think Andy's answer above should probably be the accepted answer for the question but for the sake of completeness and for anyone else who stumbles across this question:

If you are looking for a simple solution that requires you to consistently poll the backend without varying the time, (i.e. To check price changes) you could try something like this:

new Vue({
  el: '#pollingExample',
  data: {
    discountedProducts: []
  },
  methods: {
    loadData: function () {
      $.get('/store/discounts', function (response) {
        this.discountedProducts = response.discountedProducts;
      }.bind(this));
    }
  },
  mounted: function () {
    //Initial Load
    this.loadData();
    //Run every 30 seconds
   var loadData = function(){
        this.loadData();
        // Do stuff
        setTimeout(loadData, 30000);
   };
     setTimeout(loadData,30000);
  }
});

<div id="pollingExample">
  <div v-for="product in discountedProducts">{{ product.name + "-" +product.price + "$" }}</div>
</div>

When the instance is mounted we load the initial data and with the help of setTimeout we schedule our function to run every 30 seconds.

8bithero
  • 1,474
  • 1
  • 18
  • 23