How to watch for changes automatically in a API Endpoint with Vue?

Viewed 1912

I’m building an app that uses Stackoverflow’s API to get the last question of a certain tag & ouput it on my app. I have been able to get the last question on the specific tag, but now I want that automatically detect changes in the API Endpoint & fetch the last question posted without refreshing the browser or calling the function. I have tried with Computed Properties & Watchers, but I haven’t got it to work. I might be doing it wrong or my solution is not the right approach.

This is my code snippet:

<template>
  <div class="question container-fluid">
    <h1 class="my-3"
    >
    Last "<span class="question_tag">{{ tag }}</span>" Question Details
    </h1>
    <b-form
      class="my-4" 
      @submit.prevent="updateTag"
    >
      <b-form-input
        class="w-auto"
        placeholder="Enter a stackoverflow tag"
        type="text"
        v-model="newTag"
      >
      </b-form-input>
    </b-form>
    <div class="question_title my-2">
      <strong>Title: </strong> <span>{{ details.title }}</span>
    </div>
    <div class="question_status my-2">
      <strong>Question answered: </strong><span>{{ details.is_answered }}</span>
    </div>
    <div class="question_views my-2">
      <strong>Views: </strong><span>{{ details.view_count }}</span>
    </div>
    <div class="question_answers my-2">
      <strong>Answers Count: </strong><span>{{ details.answer_count }}</span>
    </div>
    <div class="question_link my-2">
      <strong>Check question: </strong>
      <a :href="details.link"
      :title="details.link"
      rel="noopener"
      target="_blank"
      >
        Here
      </a>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  name: 'QuestionInfo',
  data(){
    return {
      details: '',
      tag: `phaser-framework`,
      newTag: ''
    }
  },
  mounted() {
    this.getTag()
  },
  methods: {
    getTag(){
      axios.get(`https://api.stackexchange.com//2.2/questions?order=desc&sort=creation&tagged=${this.tag}&site=stackoverflow`).then(response => {
        this.details = response.data.items[0]
        // console.log an error if get() method is unsuccessful
      }).catch(err => {
        console.log(err)
      })
    },
    updateTag() {
      this.tag = this.newTag
      this.getTag();
    },
  },
}
</script>

EDIT:

I would like to find a Client Side solution... preferably a Vue Solution if there is any. I would like to avoid as much as possible a Server Side Solution for this feature.

2 Answers

I have found a solution. It's not the most elegant, but I finally decided to use setInterval() & make an new API call every 10 seconds. Getting fresh data every 10 seconds won't reach the Stack Exchange API's daily limit & solves my problem.

Code Snippet:

<script>
import axios from 'axios'

export default {
  name: 'QuestionInfo',
  data(){
    return {
      details: [],
      tag: `jquery`,
      newTag: ''
    }
  },
  // makes an API call on page load
  mounted() {
    this.getTag()
  },
  methods: {
    getTag(){
      setInterval(() => {
        axios.get(`https://api.stackexchange.com//2.2/questions?order=desc&sort=creation&tagged=${this.tag}&site=stackoverflow`).then(response => {
          this.details = response.data.items[0]
        // console.log an error if get() method is unsuccessful
        }).catch(err => {
          console.log(err)
        })
      }, 10000);
    },
    updateTag() {
      this.tag = this.newTag
      this.getTag();
    },
  },
}
</script>

It looks like what you're trying to do is to allow for the server to send events to the client without the client having to ask for it. There are four ways to do this.

  1. Hit the API on a regular interval.
  2. Long Polling
  3. Server Sent Events
  4. Websockets

The first is the least efficient and a waste of resources. Each new incoming connection must be established, the HTTP headers must be parsed, a query for new data must be performed, and a response (usually with no new data to offer) must be generated and delivered. The connection must then be closed and any resources cleaned up.

The second way is to set up long polling., wherein you're still connecting via an HTTP connection, but the connection is lengthened until a response comes in or it times out. This way you aren't sending as many requests.

Server-sent events will solve the problem for you and is an efficient solution for you to use, but is mono-directional (communication from the server to the client) so if you need to communicate back and forth with the API, then you might want to try something else. It depends on your needs.

Typically I would recommend websockets, but this depends on whether or not the Stackoverflow API supports the use of websockets, which is seems like is not currently the case.

For your use case, I would first look at support for websockets. If this doesn't work, look into whether server sent events will do the job for you. If this is not enough, I would recommend implementing long-polling, which should help reduce some of the resource waste.

Related