Efficiently Populating Arrays Without Blocking

Let's dive into the scenario...

Here is the template for our component

<template>
  <div>
   <loader v-show="loading"></loader> // display loading animation
   <div v-show="!loading">
     <div v-for="group in groups">
       {{group.name}}
       <div v-for="item in group.list">
         {{item.name}}
       </div>
     </div>
   </div>
  </div>
</template>

Now, let's look at the data for our component

data: function () {
    return {
        list: [],
        groups: [],
        loading: true
    }
}

1. Fetch a one-dimensional array from an API

axios.get(API_URL).then(
    (response) => {
        this.list = response.data.payload;
    }
);

The structure of the array is as follows...

[
  {
    "name": "bob",
    "group": "A"
  },
  {
    "name": "sally",
    "group": "A"
  },
  {
    "name": "john",
    "group": "B"
  },
  {
    "name": "jane",
    "group": "B"
  },
]

2. Transform the array into two dimensions based on the 'group' property

Current solution (blocking!, inefficient?)

// loading animation stops here
this.list.forEach((item, index) => {
    let hasGroupChanged = false;
    if (index === 0) {
        hasGroupChanged = true;
    } else {
        let currentGroupName = item.group;
        let previousGroupName = this.list[index - 1].group;
        hasGroupChanged = previousGroupName !== currentGroupName;
    }
    if (hasGroupChanged) {
        const group = {
            group: item.group,
            list: []
        };
        this.groups.push(group);
    }
    const groupIndex = this.groups.length - 1;
    this.groups[groupIndex].list.push(item);
});

this.loading = false;

How can we ensure that the loading animation continues until the groups are fully populated?

Answer №1

The reason why your "loading" animation appears to be "frozen" is due to the fact that JavaScript operates on a single thread. This means that when your transformation code is executing (especially with large amounts of data, causing it to run for an extended period), the browser's rendering process becomes blocked.

To address this issue, you have two options: optimize your transformation code to improve its speed or refer to this SO answer for insights and solutions on how to prevent long running operations from blocking the browser's rendering capabilities.

Answer №2

It appears that the issue lies in setting loading to false before axios has completed fetching the data, as it is the only asynchronous operation in the code.

While the .forEach loop may benefit from optimization, it is unlikely to be the root cause of the problem.

To troubleshoot, consider moving all the code inside the .then method chained off of the axios.get() call instead.

Answer №3

It's difficult for me to comment on the efficiency of your code, but one way to ensure a loading indicator continues until an async operation is complete is to halt it within a finally block:

const btn = document.getElementById('btn');
const mockLoadIndicator = document.getElementById('loading');
const data = [
  {
    "name": "bob",
    "group": "A"
  }, {
    "name": "sally",
    "group": "A"
  }, {
    "name": "john",
    "group": "B"
  }, {
    "name": "jane",
    "group": "B"
  }
];
const mockAPI = () => {
  mockLoadIndicator.style.display = 'block';
  return new Promise((resolve) => {
    setTimeout(() => resolve(data), 1000);
  });
};

btn.onclick = () => mockAPI()
.then(console.log)
.finally(() => {
  mockLoadIndicator.style.display = 'none';
});
#loading {
  position: relative;
  display: none;
  height: 10px;
  width: 10px;
  border-radius: 50%;
  background: grey;
  animation-duration: 300ms;
  animation-name: load;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

@keyframes load {
  from {
    left: 10px;
  }
  to {
    left: 40px;
  }
}
<button id="btn">Get Data</button>
<div id="loading"></div>

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

How can I specifically activate the keydown event for alphanumeric and special characters in Angular7?

I am looking to create a keydown event that will be triggered by alphanumeric or special characters like #$@. <input type="text" style="width: 70%;" [(ngModel)]= "textMessage" (keydown) ="sendTypingEvent()" > However, I want to prevent the event ...

what is the process for configuring a Universal link using javascript?

I have taken all the necessary steps to utilize a universal link. I created an AASA file, verified it using aasa-validator, and configured it in XCODE as required. Now, I am facing the challenge of setting up a hyperlink on my webpage that can redirect us ...

What are the steps to locally test my custom UI library package built with tsdx in a React.js project

I am currently utilizing tsdx to develop a React UI library, and I am looking to test it within my Next.js project before officially publishing it to the npm package. Initially, I attempted using npm link, which worked initially. However, when I made ch ...

Update the contents of TubeBufferGeometry with a new TubeBufferGeometry directly, avoiding unnecessary memory allocation

I am working with a mesh that is based on a TubeBufferGeometry. In each animation cycle, the path of the TubeBufferGeometry needs to change based on values provided at runtime. To achieve this, I want to update the geometry with a new TubeBufferGeometry ev ...

Set a variable in PHP by passing a value

In continuation of my previous post, I realized I missed a point and needed to start a new thread. Thankfully, I found a solution for the issue in my previous post and here is the final code: Scrapping code not working in php <?php $html = file_get_co ...

How can you retrieve the index of the outer repeater item within nested ng-repeaters in AngularJS?

If I have multiple ng-repeat loops nested within each other like in the following example: <div ng-repeat="outeritem in outerobject"> <div ng-repeat="inneritem in innerobject" ng-click="function(inneritem.key, $index)"></div> <d ...

Is it possible to make each letter on a page a different color using JavaScript? I've noticed that there is always an additional set of span tags before each opening tag on the page

Page hosted using Google Drive Within the JS code: var doc_part = false; //denotes if a character is not part of the visible document var page_body; //function to generate random rgb values function randomInt(max, min) { return Math.floor((Math.ran ...

Use React Router to create a link that goes to the same URL but passes along unique state

Can someone help me figure out how to open the same URL using react-router Link while passing different state each time? <Link to={items.vehicleModelId === 2 ? '/ecgo-3' : items.vehicleModelId === 3 && '/ecgo-5' ...

Tips for setting limitations on a date picker's minimum and maximum values on an iPhone using JavaScript

I have encountered an issue with my JavaScript function that sets min and max values for the input type date. While it works perfectly on Android devices, I am facing a problem on iPhone where I am unable to restrict the calendar with the specified min and ...

To begin, select and upload two files for processing. Once complete, you can download the newly generated

I'm encountering difficulties attempting to upload two files to a php script and have the page download a newly merged file without redirecting to a different page. I do not wish to store any files on the server due to their potential size (2MB) as b ...

Combining vue with deno and vscode: A guide to seamless development integration

How can I set up Visual Studio Code for a Vue project using Deno? Important note - the issues mentioned here only pertain to highlighting in VSCode, as the builds, development, and scripts are functioning correctly! Deno + Vue is an appealing choice! You ...

JavaScript: Automatically retrieving the if else function

I need help automating the calculation of the number of days a person worked based on their "in-time" and "out-time". I've tried to implement this in my JS code, but it's not working as expected. HTML <fieldset> In-Time: <input clas ...

"Enhance your Vuetify v-select by learning how to effortlessly add the same item multiple times

Vuetify offers a select field component that allows users to choose options from a list for collecting information. You can find documentation here. This component functions with checkboxes, so each time you check an item, it gets added to the end of the ...

The onWrite cloud function does not activate upon the creation of a new document

I have a collection called 'Users' that stores documents with user objects as well as a sub-collection named 'Notifications'. When a new notification is generated for a user, a corresponding document is created in the 'Notification ...

Performing a bulk create operation with Sequelize using an array

I am facing a task where I have an array of items that need to be created in the database. My approach is to check each insertion for success. If successful, I will add the item with a flag indicating success as true in a new array (results) in JSON forma ...

Transferring an array of interfaces between Angular 2 components

Encountering issues with passing an Array of data between components using @Input. Here is the code snippet: public ngOnInit() { this.applications = new Array<ApplicationEntryInterface>(); (...) let shortTermData = new ShortTermApplicationAdapte ...

What could be the reason for a variable not being assigned a value following the xmlhttp.responseText?

During the validation process of a send-fax form, I am checking if a fax has been previously sent using our software fax package. This involves a simple query to a table executed by a script, which will return text if a previous fax exists or blank if not. ...

Using express.js to transfer an uploaded image to Amazon S3

Currently, I am faced with an issue of passing an image uploaded from a react application through express to a managed s3 bucket. The s3 bucket is created and managed by the platform/host I am using, which also generates upload and access urls for me. So f ...

When utilizing Javascript's Array.push method, a nested array is generated that is inaccessible using the index

I have reviewed several articles discussing the issue of asynchronous calls returning undefined. Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference Get data from fs.readFile However, none of these articles ...

The issue of sluggishness in Material-UI when expanding the menu is causing delays

Watch Video Having trouble with the behavior of the Menu opening and closing similar to this example. The text seems slow to change position. Any ideas why? This is the devDependencies configuration I am using in webpack. "devDependencies": { ...