Anticipating the asynchronous completion of all nested recursive functions

I have a recursive function that makes asynchronous calls, using the results of those calls as arguments for subsequent recursive calls.

I am trying to find a way to wait for all recursion levels to complete simultaneously, without any delays at each level. This means that all recursions should run in parallel, followed by a final cleanup step.

To illustrate my goal, let's consider a family tree API scenario where I fetch my own record which may contain information about parents. If it does, I want to recursively fetch parent records and continue up the family tree.

These requests will be made concurrently with varying start times, and they might take different lengths of time to return. However, I need to ensure that all records are fetched before moving on to the 'Cleanup' phase.

const recurse = (url) => {
    console.log('Recurse: ', url)
    fetch(url).then((res) => {
      db.write(res.json)
      if ('parents' in res.json) {
        for (let parent of Object.values(res.json.parents)) {
          recurse(parent.URL)
        }
      }
    })
  }
}


const main = () => {
  let data = 'http://api.familytree.example.com/me'
  console.log('Start')
  recurse(data)
  console.log('Cleanup')
}

main()

Answer №1

Mastering recursion with promises can be challenging, but harnessing the power of async and await can simplify the process greatly. Check out this example showcasing the use of recursion with async functions:

const recurse = async (url) => {
  console.log('Recurse: ', url)
  const personData = await fetch(url).then(res => res.json());
  const results = [personData];
  if ('parents' in personData) {
    const parentCalls = [];
    for (let parent of personData.parents) {
      parentCalls.push(recurse(parent.URL).then(ancestors => results.push(...ancestors)));
    }
    await Promise.all(parentCalls);
  }
  
  return results;
};


const main = async () => {
  console.log('Start')
  const data = await recurse('http://api.familytree.example.com/me');
  db.write(data);
  console.log('Cleanup')
}

main()

The key concept here is to create a function (recurse) that retrieves the current data and returns a list of results. If there are parent data available, call the recurse function for each parent and append the resulting list to the existing results. The initial call will generate an array containing all items.

Consider these additional points:

  • Managing duplicates (ensure parents are not duplicated).
  • Setting recursion limits (optional but recommended).
  • Including relationship data in results (relationship data may already be present in the response).

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

Utilizing MeshPhongMaterial in THREE.js for Particle Material with Size Adjustment

My goal is to create particles that exhibit the characteristics of a Phong material, which means they react to light. I have been using the "createMultiMaterialObject" method to achieve this, and it has worked well for the most part. However, I have encoun ...

Iterate through a generic array to populate a table using ng-repeat

In the scenario I'm currently facing, I am working on creating a common reusable table structure using a directive. The goal is to display different JSON data in both the table header and body. Below is the controller code: angular.module('plun ...

Tips for making a Scroll Button

I am in the process of designing a horizontal website and I would like to incorporate two buttons, one on the left and one on the right, that allow users to scroll to the left and right, respectively. You can check out the site I am currently working on h ...

Setting a background image in vanilla-extract/css is a straightforward process that can instantly enhance

I am brand new to using vanilla-extract/CSS and I have a rather straightforward question. I am attempting to apply a background image to the body of my HTML using vanilla-extract, but I am encountering issues as I keep getting a "failed to compile" error. ...

Switching from Dom to Jquery

Seeking assistance to convert DOM values into Jquery equivalent. For instance, how can I translate the DOM code: var x = document.querySelector('#x'); into Jquery format? Any suggestions? Additionally, looking for guidance on transforming even ...

Display a helpful tooltip when hovering over elements with the use of d3-tip.js

Is it possible to display a tooltip when hovering over existing SVG elements? In this example, the elements are created during data binding. However, in my case, the circles already exist in the DOM and I need to select them right after selectedElms.enter ...

I'm curious if anyone has had success utilizing react-testing-library to effectively test change events on a draftJS Editor component

​I'm having trouble with the fireEvent.change() method. When I try to use it, I get an error saying there are no setters on the element. After that, I attempted using aria selectors instead. const DraftEditor = getByRole('textbox') Draf ...

Step-by-step guide on building a factory in Angular for a pre-existing service

Currently, I am delving into the world of angularjs and exploring articles on service and factory functionalities. One particular example that caught my attention is showcased in this ARTICLE, which includes a demonstration using a Service Fiddle. As I de ...

Implementing AngularJS drag and drop functionality in a custom directive

I am in search of an example that demonstrates similar functionality to the HTML5 File API using Angular-js. While researching directives for Angular 1.0.4, I found outdated examples that heavily rely on DOM manipulation. Here is a snippet of the pure Ja ...

Error in Firefox when converting a string to a date in JavaScript using the format mm-dd-yyyy

Hi, I am encountering an issue with converting a string in the format mm-dd-yyyy into a date object. While it works perfectly fine in Internet Explorer and Chrome, it does not work in Firefox as it returns an invalid date at times. I have also tried using ...

What is the reason behind Q.js promises becoming asynchronous once they have been resolved?

Upon encountering the following code snippet: var deferred = Q.defer(); deferred.resolve(); var a = deferred.promise.then(function() { console.log(1); }); console.log(2); I am puzzled as to why I am seeing 2, then 1 in the console. Although I ...

What is the best way to safely store a logged-in user on the client-side?

As I delve into creating a login system for my simple social media website where users can make posts and view feeds from fellow followers, I've successfully implemented user login. Upon logging in, I'm able to retrieve the user's credential ...

Diverse behaviors exhibited by an array of promises

I've developed a function that generates an array of promises: async addDefect(payload) { this.newDefect.setNote(payload.note); this.newDefect.setPriority(payload.priority); const name = await this.storage.get(StorageKeys.NAME); ...

Tips for updating a value in a React TextField using handleChange function

After clicking a button, I need to dynamically set a value in this textfield: <TextField fullWidth inputProps={{ maxLength: 75 }} key="nomeSocial" id="outlined-basic" label="Nome Social" name="nomeSocial&qu ...

One way to add a JSON object to an empty JSON array using Javascript involves pushing

Currently, I am facing an issue with an empty JSON array. shoppingCart: [] In addition to the empty array, I also have a JSON object defined as follows: let product = {"name": "name", "price": "price", "quantity": "quantity", "logoPath": "logoPath"}; M ...

Navigate to the element by clicking on the link, then apply a class to that specific element

I'm currently working with this HTML code: <div id="main"> <p>some text</p> <a id="goto-notes" href="#">see notes</a> <p>some text...</p> <div id="notes"> <p>notes here< ...

Switch the paper tab to a dropdown menu in Polymer.js

Can someone assist me in transforming the paper tab into a paper drop down menu in polymer JS? I want the drop-down to appear with a list of values when hovering over the Top menu. Activity Execution <paper-tab cla ...

Error encountered while submitting ajax request to server

When I click a button, a function is triggered with the argument insertSongPlay(newSong.songID);. After logging the value of newSong.songID, which is 90 as desired, an ajax call is made: function insertSongPlay(songID) { $.ajax ({ type: " ...

Saving a dynamic form to the database and editing it later

I have developed a dynamic form builder using jQuery UI that allows users to drag form inputs anywhere on the screen and generate a report. Now, I am trying to figure out the best approach for saving this layout to a SQL database. How can I save the struct ...

unable to execute grunt post npm installation

I'm having trouble getting grunt to work on my system. I tried installing it using npm install grunt -g It appears to have installed successfully - <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d4b3a6a1baa094e4fa0bbe7 ...