The issue of execution order in JavaScript Recursion with promises

In the process of developing a method for creating markup to be used in a web app's off-canvas navigation. One of the challenges I am facing is making an asynchronous callback to another service that provides children nodes for the parent menu node (refer to code snippet below):

function GenerateMarkup(Terms, n) {
    var termsEnum = Terms.getEnumerator();
    var html = "<ul>";

    // Handling top level terms
    while (termsEnum.moveNext()) {
        var currentTerm = termsEnum.get_current();        

        html += "<li>"

        if (currentTerm.get_termsCount() > 0) {
            var childcall = function() {
                var deferred = $.Deferred();

                html += "<a href=\"#\">" + currentTerm.get_name() + "<br><span>" + currentTerm.get_description() + "</span></a>";
                SPTermStore.GetTermsFromTermSet(currentTerm).then(function(termSet) {
                    if (typeof termSet !== undefined) {
                        deferred.resolve(GenerateMarkup(termSet, n++));
                    }
                    else
                        deferred.reject("something bad happened");
                });
                return deferred.promise();
            };

           $.when(childcall()).done(function(markup) {
                html += markup;
            });
        } // end if
        else
            html += "<a href=\"#\">" + currentTerm.get_name() + "</a>";

        html += "</li>"
    } // end while

    html += "</ul>";
    console.log("GenerateMarkup (" + n + "): " + html);
    return html;
} // end function

The issue I am encountering is related to the order in which the markup is generated; instead of completing the recursive call to GenerateMarkup synchronously, I need to wait for the returned promise so that I can append the HTML accordingly. The objective is to process the child nodes as the iteration progresses through the parent nodes.

Upon inspecting the console log output, the problem becomes clear. The first listed markup represents what is actually returned to the page, rather than a combination of the items below:

GenerateMarkup (0): <ul><li><a href="#">About<br><span>Our Company</span></a></li><li><a href="#">Portfolio<br><span>Our Properties</span></a></li><li><a href="#">Corporate Responsibility<br><span>Our Commitment</span></a></li></ul>
GenerateMarkup (0): <ul><li><a href="#">Careers</a></li><li><a href="#">Core Values</a></li><li><a href="#">Governance</a></li><li><a href="#">History</a></li></ul>
GenerateMarkup (1): <ul><li><a href="#">Core Market Strategy</a></li><li><a href="#">Our Properties</a></li></ul>
GenerateMarkup (2): <ul><li><a href="#">Community Involvement</a></li><li><a href="#">CSR Report</a></li><li><a href="#">Diversity</a></li><li><a href="#">Sustainability</a></li></ul>

I would greatly appreciate any assistance with this matter.

Answer №1

To efficiently handle multiple asynchronous calls, consider iterating through the termsenumerator and storing the data in a deferred array. After collecting all the data, utilize $when to synchronize the processing tasks. Refer to the example code snippet below:

 var asyncTasks = [];
 for (var j = 0; j < termsenumerator; j++) {              
      asyncTasks.push(Extract desired data and add it to this array);             
 }

//Now that all results (deferred) are gathered, execute the following.
        $.when.apply($, asyncTasks).done(function () {

            var processedData = [];

            for (var k = 0; k < arguments.length; k++) {
                var itemData = arguments[k][2];                   
                applyMarkupWithData(processedData.responseJSON.d, k);


            };

        });

Answer №2

Async promises do not always return in the order they are promised, making their sequencing unpredictable.

To ensure a specific order of execution, consider chaining the promises together so they run sequentially as expected. Learn more about chaining promises with Promise.then.

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

What is the correct way to retrieve a JSON object instead of getting [Object object]?

Creating a basic web scraper integrated with mongoDB. Even though the API returns the JSON object in the correct format, when trying to append it to a bootstrap card on the page, I'm getting [Object object]. Below is my JavaScript code running on th ...

Compatibility issues between jQuery and AngularJS are causing problems

Currently, I am facing a compatibility issue between RequireJS and Angular in my setup. Everything functions without any problems when using jQuery version 1.7.2. However, I wanted to upgrade to jQuery 1.8.1 along with jQuery UI, but unfortunately, my Angu ...

What exactly is the purpose of the script type importmap?

Can you explain the role of <script type="importmap"> and why it has become necessary for my code to function properly? <script type="importmap"> { "imports": { "three": "http ...

Can someone provide guidance on creating a calculator using the Switch statement in Javascript?

Introduction to HTML: <div id="content"> <div id="calculator-container"> <form name="calc"> <!-- The form is named "calc" --> <label for="output">A Simple Calculator</label> & ...

Sequencing asynchronous functions in Angular: Ensuring one function runs before another

When working with a save function that requires you to call another function to retrieve the revision number and make an API call, both of which are asynchronous in nature, how can you ensure one function waits for the other to execute? $scope.getRevision ...

What are the steps for integrating an external API into a React project?

Apologies for any potential repetition, as this question may be commonly asked. I am currently working with React, Express, CORS, node, and postgres databases. My objective is to utilize the following API to retrieve real-time prices for metals: https://me ...

Destructuring array in React using Javascript

I'm currently exploring ReactJS and I'm facing a dilemma in understanding the destructuring process in the code snippet below: const IngredientsList = ({ list }) => React.createElement('ul', null, list.map((ingredient, i ...

Eliminate the standard blue border that appears when control-clicking on table elements

I've encountered this question before, but unfortunately none of the solutions provided have worked for me. Some things I've attempted are: Using event.preventDefault() - did not produce the desired result. Removing user-select from CS ...

Tips to Avoid Multiple Executions of Javascript Code due to Caching

When I make a request to my Asp.net-MVC application, it returns a partial-view. public ActionResult AccountDetails() { return PartialView("~/Views/partials/Account/Details.cshtml"); } To load the partial view in my form, I use the following ...

Challenges regarding OAuth2 and the angular-auth2-oidc Library - Utilizing PKCE Code Flow

As a newcomer to OAuth2 and the angular-auth2-oidc library, I may make some beginner mistakes, so please bear with me. MY GOAL: I aim to have a user click on the login link on the home page, be directed to the provider's site to log in, and then retu ...

Utilizing jQuery UI to dynamically alter CSS classes

I'm currently working on a project and could use some assistance. I have divs that are droppable using jQuery UI. While everything is functioning properly and I can drag and drop, I am looking to modify the opacity of the div I am dragging by changing ...

Angular is throwing a RangeError due to exceeding the maximum call stack size

Encountering a stackOverflow error in my Angular app. (see updates at the end) The main issue lies within my component structure, which consists of two components: the equipment component with equipment information and the socket component displaying conn ...

Discovering the URL of an AJAX request on any given website

Is there a way to retrieve the URLs of AJAX requests that are sent by the current page on a website using a browser or another tool? ...

Issues with Angular displaying filter incorrectly

Whenever a user chooses a tag, I want to show only the posts that have that specific tag. For instance, if a user selects the '#C#' tag, only posts with this tag should be displayed. This is how my system is set up: I have an array of blogs that ...

Passing variables from AJAX response to PHP using a passthru function

In my PHP file, I have implemented a functionality where certain checkboxes are checked and upon clicking a button, a JavaScript file is triggered. The JavaScript code snippet used is as follows: $.ajax ({ type: "POST", url: "decisionExec.php", ...

In Javascript, navigate to a specific section by scrolling down

Currently, I am in the process of enhancing my portfolio website. My goal is to incorporate a CSS class once the user scrolls to a specific section on the page. (I plan to achieve this using a JavaScript event). One approach I am considering is initially ...

Vue.js: The Power of Manipulating Strings

Why is the filter method not working with this.userId, but it is working with the hard-coded value "admin"? How can I resolve this issue? computed: { UidMessages: function() { return this.Messages.filter(function(m) { return m ...

Redux/React project bundle

I am currently attempting to incorporate the package https://www.npmjs.com/package/is-url into my React/Redux project, but I'm unsure about how to go about importing it. Are there any other ES6-compatible installation options that you would recommend ...

Combining two objects in node-red: A step-by-step guide

msg.payload : Object object HAMK307: object a_temperature: 23.1 a_humidity: 46 a_brightness: 3703.05 a_lights: "on" a_presence: "empty" r_temperature: 35.59 r_humidity: 30.46 r_pressure: 994.43 a_time: object ID: "HAMK-307" m ...

The Wordpress plugin's Ajax function is giving back a response value of zero

I'm facing an issue where I am attempting to send AJAX data to my wordpress table, but the response I receive from my PHP script is always a 0. This problem arises specifically on the admin side of things. Can anyone provide assistance? Furthermore, ...