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

How to fetch files using URL in JavaScript

I need a solution for automatically downloading multiple PDF files from Google Drive and Docs using their URLs with JavaScript code. I don't want to manually go to each link to download the files. Although I've researched various answers on Stac ...

Decision on how to exchange data (JSON or traditional method)

In my current project, I am developing a user-friendly application that allows users to design their own web interface using various tools. Users can create drag-and-drop elements and I need to store this data in a database once they finalize their desig ...

Get the JSON file from Firebase storage

My query boils down to this: Within my vue.js application, I am uploading a json file to a firebase storage bucket. However, when attempting to download the file for use within the app, I encounter an "Uncaught (in promise) undefined" error. The goal is t ...

Is there a way to obtain the coordinates of an SVG element by simply clicking on a specific point?

I'm still learning about SVG and I'm trying to trigger an event that captures the click coordinates when clicking on the SVG. I have a few questions: Since I'm using Angular, I'm unsure if it's possible to keep my function in th ...

Unexpected symbol in JSON parsing with JavaScript

let information; $.ajax({ url: link, type: 'POST', dataType: "json", success: function (data, textStatus) { information = data; alert(data.name); } }); I am attempting to retrieve JSON-encoded data from a spe ...

JavaScript: The Battle of Anonymity - Anonymous Functions vs Helper

I'm currently grappling with a piece of functional style code that is featured in the book Eloquent Javascript: Here's the issue I'm facing: When I have the count() function passing an anonymous function to reduce(), everything seems to wor ...

Enhance your images with the Tiptap extension for customizable captions

click here for image description I am looking to include an image along with an editable caption using the tiptap extension Check out this link for more information I found a great example with ProseMirror, but I'm wondering if it's possible ...

Launching an embedded webpage in a separate tab within the main browser window

In my current setup, I have implemented an iframe within the main window. The iframe includes a form where users can input data and submit it. Currently, I achieve the submission with the following code: var openURL = '/results/finalpage'; windo ...

The HTTP request is malfunctioning in a different location

I'm facing an issue where my code works in the w3schools code editor, but not on localhost or cpanel host. When I try to run it on another host, it gives me a bad request and doesn't return the answer. Here is the code snippet that I am working ...

Having trouble getting the Bootstrap modal form to submit when using Knockout's submit binding?

Check out my jsFiddle example by clicking here. I am currently working on a form within a bootstrap modal. The problem I'm facing is that the knockout submit binding doesn't get executed unless the user clicks on the submit input. It seems like ...

Having trouble displaying the API response data on the screen in Next.js

I am currently experiencing an issue with my OCR API that is supposed to return text from a given image. The data is being received on the client side and can be seen in the console. However, for some reason, the element is not updating with the data. Bel ...

Troubleshooting: Why Your Angular Data Binding is Failing

I am integrating a WCF REST service with an AngularJS application. My goal is to retrieve account information based on the account number provided, however, I am encountering an issue where the text "Account_Type" is displayed three times before showing th ...

The checkbox filter in Angular 6 has the ability to replace the previously selected

I've been working on creating a filter system using checkboxes. Below is a snippet of the code I'm currently using: filter.pipe.ts import { Pipe, PipeTransform, Injectable } from '@angular/core'; @Pipe({ name: 'filter2' }) ...

Modify the class of the dropdown and heading 2 elements if they meet specific conditions using Animate.css

Is it possible to add a class using jQuery when two specific conditions are met? 1) If the dropdown selection is either "acting" or "backstage" 2) If the membership status is set to "Non-member" If both of these requirements are fulfilled, I would like ...

What is the best way to divide data prior to uploading it?

I am currently working on updating a function that sends data to a server, and I need to modify it so that it can upload the data in chunks. The original implementation of the function is as follows: private async updateDatasource(variableName: strin ...

What is the best way to add a border around an image along with a button using VueJS?

I am struggling to link a button and an image in VueJS to display a border around the picture. While I can successfully display the border on the button, I am unsure how to extend it to the image as well. Vue.component('my-button', 'my-img& ...

Set a variable to a specific cell within a table

I've been attempting to insert images into a table and have had success so far - clicking cycles through the available options. However, I've encountered an issue where the counter is not cell-specific but rather global. Is there a way to create ...

Struggling to incorporate pagination with axios in my code

As a newcomer to the world of REACT, I am currently delving into the realm of implementing pagination in my React project using axios. The API that I am utilizing (swapi.dev) boasts a total of 87 characters. Upon submitting a GET request with , only 10 cha ...

Change a JavaScript object into an array with different options while still maintaining the keys

I am attempting to transform the following JavaScript object: image_uploads: [ 0: { upload_id: 50, }, 1: { upload_id: 51, }, 2: { upload_id: 52, }, ] Into separate entries using this structure for inclusion in the body of a POST r ...

Incorporating a JavaScript object into a DataTables JSON structure: A practical guide

I have integrated the datatables jQuery plugin into my project and I am looking to streamline the process by creating a shared function to easily call a datatable from multiple pages without duplicating code. To achieve this, I am attempting to define the ...