Unleashing a cascade of infinite promises

When it comes to handling an expensive computation within a function that is called frequently and needs to return quickly, my approach involves chaining promises together with this. This method seems to be effective in ensuring that computations occur sequentially rather than rapidly.

let promiseChain = Promise.resolve();
function func() {
  (async () => {
    promiseChain = promiseChain.then(() => {
      doComputation(); // does not provide a return value
    });
  })();
}

(Edit)
To elaborate further:
The actual implementation of the func I am developing looks more like this:

function func() { // triggered whenever the DOM changes
  const node = capture(document); // This essentially creates a clone of the DOM
  (async () => {
    promiseChain = promiseChain.then(() => {
      doComputation(node); // does not provide a return value
    });
  })();
}

The reason for the necessity of quickly exiting from func is due to rapid DOM changes, which need to be captured promptly. As a solution, running the content asynchronously within func can aid in achieving this objective. While the computation itself may be synchronous and requires sequential execution, utilizing then to chain them together serves this purpose effectively.

Answer №1

JavaScript operates on a single thread, which means synchronous calculations cannot be performed asynchronously on the main thread. Therefore, using a promise chain in this scenario doesn't have any practical purpose. Instead, you can opt for traditional synchronous code and loop through your calculation functions to execute them.

For executing a sequence of asynchronous tasks, you can utilize the async/await feature by looping through them.

If you need to carry out resource-intensive computations without causing UI blockages, consider utilizing Web workers: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

An uncomplicated approach to performing computations in a queued worker could be demonstrated as follows:

let taskId = 1;

const executeFunctionInWorker = function(fn){

  const id = taskId++;
  
  return new Promise(resolve => {
    const blob = new Blob([`
    let start = performance.now();
    (${fn.toString()})();
    postMessage({duration: performance.now() - start});
    `], {type: 'application/javascript'});
    const worker = new Worker(URL.createObjectURL(blob));
    worker.addEventListener('message', e => {
      resolve(`Finished task ${id} in ${e.data.duration}ms`);
    });
  });
  
};

const doComputation = () => {
  let count = 1000;
  while(count--){
    structuredClone(Array.from({length: 5000}, () => Math.random()));      
  }
};

class PromiseQueue{
  tasks = [];
  async push(task){
    const starting = this.tasks.length === 0;
    this.tasks.push(task);
    if(starting){
      let task;
      while(task = this.tasks[0]){
        const result = await task();
        this.tasks.shift();
        console.log(result);
      }
    }
  }
};

const queue = new PromiseQueue;

const push = () => Array.from({length: 5}, () => queue.push(() => executeFunctionInWorker(doComputation)));
<button onclick="push()">Queue 5 tasks</button>
<div>You can press any number you want without waiting the previous tasks to complete</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

Inserting data into a JavaScript database

When attempting to add a new row to a datatable and submit it to a JSP for database insertion, an error is encountered. The error message reads: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the r ...

How can I resize an element using jQuery resizable and then revert it back to its original size with a button click?

I need help figuring out how to revert an element back to its original size after it has been modified with .resizable. I attempted the following: <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="//code. ...

Retrieve the keys of a JSON object from an unfamiliar JSON format

I have a challenge involving an algorithm where I need to extract all keys (including nested objects and arrays of objects) from a JSON file with unknown structures and store them in one array. { "key": "value to array", "key": [{ "key": { "k ...

How can I optimize my .find query for a MongoDB GET request to achieve maximum performance?

I'm struggling to figure out how to retrieve only the last item stored in my database using a GET request. While I can successfully get the desired output in the mongo shell (as shown below), I haven't been able to replicate it in my GET route qu ...

Understanding the document.domain feature in Javascript

I have a website called foo.com hosted on server bar. Within this website, I have created a subdomain called api.foo.com. To connect the subdomain with Google Apps, I have set up a CNAME entry pointing to ghs.google.com. Now, I am facing an issue when att ...

The variable is currently undefined because it has an array assigned to it

Upon selecting multiple checkboxes for variants, I am retrieving checked data using the following method: get selectedIdsFromViolCategoriesFormArray(): string[] { return this.violCategories .filter((cat, catIdx) => this.violCategoriesFormArr. ...

Accessing router parameters in Vuex actions

Is there a more efficient way to pass router params into Vuex actions for a large form? edit_sport_type({ rootState, state, commit }, event) { const sportName = rootState.route.params.sportName <------- const payload = {sportName, event} ...

Restrict the amount of displayed information in Vue

I'm having trouble creating a Vue button that limits the display of items fetched from an API. The goal is to only show 3 out of 10 questions initially, and when the "showmore" button is clicked, another set of 3 should be displayed, and so on. Howeve ...

Clicking again on the second onclick attribute

I have an image file named image1.png. When the button is clicked for the first time, I want it to change to image2.png. Then, when the button is clicked for a second time, I want it to change to yet another image, image3.png. So far, I've successful ...

Concealing specific elements in Angular by utilizing ng-class conditions

Here's the code snippet I am currently working with: <tr ng-repeat="version in allVersions" ng-class="{{ version['active'] == 'true' ? 'active' : 'inactive' }}"> </tr> The ng-class is functioning ...

Creating markers from Mysql database is a simple and efficient process

On my website, I have an array of markers that I use to display locations on a Google map. The array format I currently use is: generateMarkers([['Location', lat, long], ['Location2', lat2, long2],['Location3', lat3, long]3]) ...

Troubleshooting issue with the JQuery .change function not working in HTML <select>

I can't figure out why this code isn't working. It seems like it should be simple enough. Take a look at my drop-down menu code: <div> <form> <select id='yearDropdown'> <c:forEach var="year ...

What is the best way to define the scope of an HTTP request within my application?

I need assistance with setting the scope for an http request in my Ionic App. Our Backend is built with Node.JS using the Hapi Framework. Since I primarily work on the frontend, I lack knowledge of server-side operations. Currently, I am able to successfu ...

Using the onClick function to set attributes in React JS

I am currently working with 2 functions: addBookmark() and removeBookmark(). There is a variable called IsBookmarked that can be either true or false. In my JSX code related to bookmarks, it looks like this: {props.singleCompany.IsBookmarked ? ( ...

Implement AJAX in order to circumvent fees from Google Maps and display maps exclusively upon user interaction by clicking a designated button

Starting July 16, 2018, the Google Maps API is no longer completely free. After July 16, 2018, in order to continue utilizing the Google Maps Platform APIs, you must activate billing for each of your projects. (https://developers.google.com/maps/documentat ...

In PHP, a boolean variable will not display on the webpage when echoed

I am facing an issue with my PHP code where certain variables are not being echoed properly in the generated JavaScript. The code is designed to check if specific values are assigned in the $_GET global array and assign default values if they are not prese ...

Using maxCDN to deliver static files within a Node application

Our current project is built using keystone and nunjucks, with all paths to static files following the format /stc/img/someimage.jpg. I am looking for a way to serve these files through middleware in our node server from maxCDN. Is there a solution that ...

What is the best way to eliminate the ' from every element in an array in this situation?

My form has hidden fields with values enclosed in single quotes like 'enable'. Using jQuery, I extract these values and push them into an array. This array is then sent to a PHP file using JavaScript through the url attribute of the jQuery AJAX m ...

Looking for assistance with a JavaScript code snippet

I have encountered an issue while iterating through receipts in the given code snippet. The objective is to fetch the receipt number for each receipt and add it to a JSON object. However, I am facing a problem where the same receipt is appearing in two sep ...

Generating Multilayered PDF files with JavaScript in NodeJS

After reviewing the documentation for PDFMake, PDFKit, and WPS: PostScript for the Web, I couldn't find any information beyond background layers. It seems like Optional Content Groups might be what I need, but I'm unsure how to handle them using ...