Execute the function only in response to changes in the data

I have a scenario where I am making an ajax call every 3 seconds to keep my app updated with rapidly changing information. However, the expensive function that I run inside the $.done() callback is causing my app to slow down. I want to optimize this process by only running the function if the data returned from the ajax call is different from what I already have in the data object. Can someone suggest the best approach in Vue.js for achieving this?

var app = new Vue({
  data: {
    people : []
  },
  methods: {
    loadPeople() {
        $.ajax({
            method: 'POST',
            dataType: 'json',
            url: base_url + 'users/getParticipants2/' + event_id
        }).done(data => {
        //this.people is an array
        //data is an array
        //I only want to do these two things if data is different from what I had in this.people previously
            this.people = data;  
            this.filterPeople();
        });
    }
  }
});

Answer №1

Vue provides a helpful tool that might be applicable in this situation. Internally, Vue utilizes a function called looseEqual, which can be accessed via _q export and invoked as this._q().

You can make use of this function to only update your property when the new data fetched differs from the existing data. Check out the demo below.

new Vue({
  el: '#app',
  data: {
    people: []
  },
  methods: {
  async fetchPeople() {
    let response = await axios.get('https://jsonplaceholder.typicode.com/users');
      if (this._q(this.people, response.data)) {
        console.log("data didn't change, no need to update");
        return;
      }
      console.log("data changed, updating");
      this.people = response.data;
    }
  }
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<div id="app">
  <button @click="fetchPeople">Fetch People</button>
  <ul>
    <li v-for="p in people">{{ p.name }}</li>
  </ul>
</div>

One downside is that this function is internal (indicated by the _ prefix), so it may undergo changes in the future. Initially, its implementation was:

function looseEqual(o1, o2) {
    return JSON.stringify(o1) === JSON.stringify(o2);
}

In case of any changes, you always have the fallback option to rely on.

Answer №2

After carefully reviewing your explanation and the coding conventions utilized in the snippet you provided, I have a few key suggestions that may offer some insight.

If the main purpose of your filterPeople() function is to filter and update the view, it's possible that you are approaching this task from the wrong angle.

In the absence of full knowledge regarding the operations of the filterPeople() function, my advice would be to consider defining a vue.js filter if your intention is indeed to conduct a filtering operation. For instance, let's assume you wish to apply the filterPeople filter on the list of participants returned.

Vue.filter('filterPeople', function (newer, older) {
   if (older == newer) {
       return older
    }

    // Otherwise, proceed with filtering and return 'newer' 

 });

var endpoint  = '/users/participants';

new Vue ({
    el: '#app',
    data: {
        participants: null,
        previous: null
    },
    methods:{
        getParticipants: function(){
               this.$http.get(endpoint).then(function(response){
                   this.previous = this.particpants;
                   this.participants = response.data;
                }, 
                function(error){
                  console.log(error.statusText);
                }
              })
          },
          mounted: function () {
            this.getParticipants();
         }
  });

A typical representation within your html might resemble the following example.

<div id="app">
     {participants | filterPeople(previous)}
<div>

This approach is merely a suggested course of action (represented in pseudo code format). Another viable option could involve using a v-if directive to display the binding effects with or without the filter.

Furthermore, there appears to be a discrepancy where you reference a getParticipants endpoint while employing an HTTP post method. Ideally, I would recommend naming the endpoint as /users/participants and utilizing a GET method for retrieving participants, along with a POST method (on the same endpoint) that accepts a JSON request body for participant creation. Naming an endpoint based on an action like getParticipants is less than optimal; instead, endpoints should reflect the resource they pertain to. Web service "methods" typically align more closely with SOAP principles.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

arrange the elements in an array list alphabetically by name using the lodash library

Is there a way to alphabetically sort the names in an array list using JavaScript? I attempted to achieve this with the following code: const sample = [ { name: "AddMain", mesg: "test000" }, { name: "Ballside", ...

Error: Vue cannot be created due to lack of permissions

Can anyone assist me with this issue I'm having while trying to install a Vue app using the command "npm init vue@latest"? Unfortunately, I keep encountering an error and I've tried various solutions such as executing "chmod -R 755 .npm" and "sud ...

ContainerView: challenges encountered when dynamically inserting views

ContainerView.pushObject() does not automatically connect dynamically added views with a Container object. The absence of an auto-wired container leads to a rendering error when a view renders a template containing a handlebars render helper. SIMPLE SCENA ...

Disabling a DropDownList in ASP MVC when a checkbox is marked: A step-by-step guide

Currently, I am in the process of developing an application using ASP .Net MVC 3 with C# and SQL Server 2005. Additionally, I am incorporating Entity Framework along with the Code First Method for this project Within a specific view, there are 2 checkbox ...

How to implement server-side rendering in Next.js 14 with GraphQL queries

I recently completed a Next.js project and configured Apollo Client. I integrated it with my components, as shown in my layout.tsx file: import { Inter } from "next/font/google"; import "./globals.css"; import ApolloProviderClient from ...

Erroneous Marker Placement Detected

Here is the data from my DataTable: Country Types of sales Total sales($) Name State United states of America chemicals 12662871 Obama GA Unite ...

Encountering issue with Konva/Vue-Konva: receiving a TypeError at client.js line 227 stating that Konva.Layer is not a

I am integrating Konva/Vue-Konva into my Nuxtjs project to create a drawing feature where users can freely draw rectangles on the canvas by clicking the Add Node button. However, I encountered an error: client.js:227 TypeError: Konva.Layer is not a constr ...

Vue-bootstrap spinbutton form with customizable parameters

I am in need of a custom formatter function for the b-form-spinbutton component that depends on my data. I want to pass an extra argument to the :formatter-fn property in the code snippet below, but it is not working as expected. <b-form-spinbutton :for ...

Is there a way to send an array of objects as parameters in JavaScript?

I have an array of objects with the same key name. My goal is to pass each address key inside those objects as a parameter to my API. How can I achieve this? The response I receive looks something like this: { '0': { address: 'abcd' }, ...

A guide on updating a boolean field in the database using ajax

Here is a piece of my html code: <form action="" method="post"> {% csrf_token %} {% if donate.is_taken == False %} <br> <button type="submit" class="btn" name="taken_or_not" ...

Reduce the use of if statements

Is there a way to optimize this function by reducing the number of if statements? The currentFeatures are determined by a slider in another file. The cost is updated if the currentFeatures do not match the previousFeatures, and if the user changes it back ...

What is the process for displaying the current bitcoin price on an HTML page using API integration?

I'm looking to develop an application that can display the current Bitcoin price by fetching data from the API at . I want to showcase this information within an h2 element. Any suggestions on how I could achieve this? Thank you in advance. const e ...

Issue with MUI Autocomplete not showing selected name on initial option selection

I encountered a strange issue with the Autocomplete component from Material UI. Here is the code snippet in question: const [isContactListInitialised, setContactListInitialised] = useState(false); const toggleContactListInitialized = () => { setContactL ...

Sharing the outcome of a $.get request with another function for optimal results

I am facing an issue with the callback function of the jquery $.get() ajax function. Currently, I am working with the DataTables plugin and attempting to implement the "expanding row to see children details" example from (https://www.datatables.net/exam ...

What is the best way to upload an image, pass it to my controller for validation, and finally store it in my database?

I am currently working on a project using Laravel 5.4 and Vue.js. I have a file named AddProduct.vue which contains a form. Everything in the form is working fine except for uploading an image. Can someone guide me on what onchange method I should use to u ...

What is the method for displaying x-axis dates below a highchart?

I'm encountering an issue with Highcharts where dates are not showing under the chart when passing series data as an array of objects. See result image The documentation mentions using an object instead of an array ([1649153340000, 45]docs I need t ...

Ways to simulate a function that is a part of an internal object

Is there a way to mock a method from an object within my UnderTest class? When the Update method is triggered by an event from a child component, I need to mock the service.saveNewElement(data) method in order to test data in the then() block. <script ...

Vuejs v-for nested loops

After spending countless hours researching, I am determined to solve this problem. My objective is to create a questionnaire similar to a Google Form, with question groups, questions, and answers. The structure of my data looks like this: question_group: ...

Using AngularJS to pass the output of a unique filter to another custom filter

I have successfully developed two custom filters and am attempting to utilize them both within an ng-repeat loop. Is there a way for me to pass the output of the first filter as an input for the second one? I attempted using 'as' keyword in ng- ...

PhpStorm 2019.2 introduces Material UI components that have optional props instead of being mandatory

My PhpStorm 2019.2 keeps showing me a notification that the Button component from Material UI needs to have an added href prop because it is required. However, when I refer to the Material UI API, I see something different. Take a look at this screenshot: ...