Show that a CPU-intensive JavaScript function is executing (animated GIF spinners do not spin)

Displaying animated indicator or spinner gifs, then hiding them, is an effective way to communicate to the user that their action is being processed. This helps to assure the user that something is happening while they wait for the action to complete, especially when loading data from a server via AJAX.

One issue I've encountered is that if the slowdown is caused by a processor-intensive function, the gif freezes.

When a processor-hungry function is running, most browsers will cause the animated GIF to stop animating. This can give the user the false impression that something has gone wrong, when in reality the process is still functioning.

Example on JSBIN

In the example, clicking the "This is slow" button will tie up the processor for a few seconds, depending on the specs of your PC. You can adjust the duration of this process in the HTML with the "data-reps" attribute.

  • Expected Outcome: The animation starts running on click, and when the process is finished, the text changes (usually, the indicator would be hidden as well, but it's left spinning in this example for clarity).
  • Actual Result: The animation starts but freezes until the process completes, leading to the misconception that something has gone wrong (until suddenly, it finishes).

Is there a way to indicate a running process without freezing if JavaScript is keeping the processor busy? If an animated solution is not feasible, I may resort to displaying and hiding a static text message like Loading..., although an animated indicator is more visually engaging.


In case you're wondering why I'm using processor-intensive code instead of optimizing it: The code involves complex rendering that is necessary. While the code itself is efficient, the complexity of its operation demands heavy processing. It only takes a few seconds, but it can still lead to user frustration, hence the importance of indicators for good UX.


Another issue with using gif spinners for processor-heavy functions is that the spinner may not show until all synchronous code has executed - meaning it might not display until it's time to hide it.

  • JSBIN example
  • An easy workaround I've found (used in the previous example) is to wrap everything after showing the indicator in
    setTimeout(function(){ ... }, 50);
    to make it asynchronous. While this works, it's not the cleanest solution - there may be a better approach.

I believe there must be a standard method for handling indicators during processor-intensive loading that I'm not aware of, or perhaps using text like Loading... with setTimeout is common practice? My searches have not yielded any relevant results, as most related issues turn out to be unrelated.


Edit: Some valuable suggestions have been provided in the comments. Here are some more specifics about my particular issue:

  • The complex process involves manipulating large JSON data files in memory (JavaScript operations after loading the files) and rendering SVG visualizations, including a detailed, zoomable world map using Raphael.js. Some parts involve DOM manipulation, while others do not.
  • Unfortunately, I need to support IE8, but I could provide minimal fallback for IE8/IE9 users like a simple Loading... text, and offer a more modern solution for other browsers.

Answer №1

In today's web browsers, CSS animations are now able to run independently from the user interface thread if the animation is created using a transform rather than by changing properties. You can read more about this in an article located at .

As an illustration, there are CSS spinners featured on that utilize transforms and will not freeze even when the user interface thread is occupied (such as the final spinner on that webpage).

Answer №2

In previous experiences, I've encountered similar issues which were resolved by optimizing tasks in smaller increments based on user interactions. For your situation, adjusting zoom levels could trigger different rendering processes, allowing you to focus only on what is visible to the user (with a buffer margin).

A potential workaround for cross-browser compatibility could involve using setTimeout to prioritize the UI thread. Group your tasks into batches and link them using multiple setTimeout calls. This method may increase processing time, but it ensures that users receive feedback. If your tasks can be segmented easily, you might also consider implementing a progress bar to enhance the user experience.

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

Using jQuery to pass UI positions as percentages instead of screen positions

Currently, I have implemented the following code to send $_GET values to a PHP page: $.get('/includes/sticky_notes/update_position.php',{ x : ui.position.left, y : ui.position.top, z : zIndex, id : parseInt(ui. ...

How can I preserve the line break in a textarea using PHP?

Is it possible to maintain line breaks in a textarea using PHP? Currently, I have a temporary solution that involves using the exec function to run a shell command, but I would prefer a purely PHP approach. Below is my temporary script - can you help me mo ...

Selenium was unsuccessful in finding the text on the webpage

Trying to extract Amazon reviews for a specific product, the text for ratings cannot be located using selenium. However, it can be easily extracted using soup. Link to page: Sample code using Soup: link='same link as mentioned above' url=requ ...

Issue: The initial parameter should be a File or Blob object

Hey there! I'm currently utilizing the compressorjs plugin for compressing images, but I'm encountering an issue when selecting images. You can find out more about the plugin here. Here is my code snippet: window.resolveLocalFileSystemURL( ...

Tips on eliminating the gap between two flex items while adjusting their size

Can anyone assist me with my code? Here is the current version: https://i.stack.imgur.com/00RGC.png I want it to resemble this: https://i.stack.imgur.com/JSclD.png You can find all my attempted media queries in the CSS comments at the end. Please let m ...

Display an icon to act as a separator between icons in CSS styling

Is there a way to display a spacer line before and after icons (cross symbols) while excluding the spacer line before and after buttons carrying the word "Cancel"? How can this be achieved? This is my CSS file: .Container > *:first-child::before, .Con ...

I am encountering an issue where JSON.parse is returning undefined when trying to

Upon receiving a string from my server, I am attempting to parse it into a JSON object. Here is the string and relevant code snippet: stringToParse = "\"{'female': 16, 'brand': 75, 'male': 8}\"" d ...

Use a dropdown menu to update the selected value

Issue with displaying drop down values in the second list, despite trying various solutions. When a user selects a country, the corresponding state should be populated from the database into the second drop-down. Any assistance would be greatly appreciated ...

Is there a method to instruct angular-cli (for angular 2) to produce a minified version of css files?

When running "ng serve" in angular-cli, the generated css is not minified as expected. Is there a specific setting to configure in angular-cli-build or an additional plugin to install? This is the content of my angular-cli-build.js file: var Angular2App ...

Adding data to a deeply nested array structure in MongoDB using Mongoose

My backend, built with Node.js using Express and MongoDB through Mongoose, features an array structure comprising three levels. At the third level, some files are stored. However, I now face the challenge of dynamically adding entries at any level based on ...

Find out whether the object is located behind another item

Is there a method to determine if elementA is "obscured" by another element, meaning it is not visible to the user? We could potentially achieve this using stacking context, but the challenge lies in identifying which elements to compare. This would requi ...

Retrieve the unfinished user input from React's Material UI Autocomplete

I've implemented Material UI's Autocomplete input with react-hook-form as shown below: import React from "react"; import {Controller} from "react-hook-form"; import {Autocomplete} from "@mui/material"; export const ...

Is there a way to showcase the string message from BadRequest(message) utilizing Ajax?

I am currently working on implementing an API Controller. public ActionResult<Campaigns> AddCampaign([Bind("Name, Venue, AssignedTo, StartedOn, CompletedOn")] Campaigns campaigns) { try { if (ModelState.IsVal ...

jQuery Masonry now renders "row blocks" as opposed to trying to fit elements into place

Have you ever heard of the jQuery masonry plugin? It's a great tool for placing images in "blocks" instead of trying to squeeze them into empty spaces. Take a look at this explanation: But how can we minimize those pesky "voids"? HTML: <!-- This ...

How to Create a Bootstrap 4 Fixed Bottom Navigation with a Dropup Feature?

After thoroughly researching the site, I have not found a solution that works with this particular approach. In order to create the following template, I utilized Pingendo. .dropup .dropdown-menu { top: auto; bottom: 100%; margin-bottom: .125rem; ...

Instructions on creating a solid wall in Three.js using boxGeometry to prevent objects from passing through

I recently created a 3D maze using threejs, where I utilized BoxGeometry to construct walls that the game object cannot pass through. In my research, I discovered the importance of collision detection in ensuring the object does not go through the wall. ...

Adjustable height for the absolute element

Having a bit of an issue with the height of the absolute div. About: .wrapper - I want the wrapper to automatically adjust its height but be limited by a max-height. (No scrolling for the wrapper) .title - Just a title .content - The problem aris ...

Instructions for developing an HTML element slider using mouse dragging

I've come across plenty of slider plugins that either only allow clicking to view the next image, or if they do support mouse drag or touch capabilities, they are limited to images. Does anyone know of a plugin or method to create a mouse drag slider ...

Why aren't my Post Variables being passed through my jQuery Ajax Request?

My goal is to utilize a full calendar ajax call to add events to the database. After testing the PDO query separately and confirming its functionality, I have identified an issue with the ajax post. The code snippet below showcases the ajax call in defaul ...

Guide to converting a string into an undefined type

I've been working on parsing a csv file: let lines = csvData.split(/\r\n|\n/); let headers = lines[0].split(','); for (let i = 1; i < lines.length; i++) { let values = lines[i].split(','); ...