Transforming an async/await function into its ES5 counterpart

Currently, I am making modifications to an application that processes REST API calls in batches, such as executing 500 total calls in groups of 10. I require help in downgrading my JavaScript function, which currently utilizes ES6+ features, to an ES5 equivalent (without arrow functions or async/await).

In the initial version of my application, which was utilized in environments supporting ES6+ functions like arrow functions and async/await, the working function looked like this:

Original Function:

// Async function to process rest calls in batches
const searchIssues = async (restCalls, batchSize, loadingText) => {
    const restCallsLength = restCalls.length;
    var issues = [];
    for (let i = 0; i < restCallsLength; i += batchSize) {
        //create batch of requests
        var requests = restCalls.slice(i, i + batchSize).map(restCall => {
            return fetch(restCall)
                .then(function(fieldResponse) {
                    return fieldResponse.json()
                })
                .then(d => {
                    response = d.issues;

                    //for each issue in response, push to issues array
                    response.forEach(issue => {
                        issue.fields.key = issue.key
                        issues.push(issue.fields)
                    });
                })
        })
        await Promise.all(requests)
            .catch(e => console.log(`Error in processing batch ${i} - ${e}`)) 

        d3.selectAll(".loading-text")
            .text(loadingText + ": " + parseInt((i / restCallsLength) * 100) + "%")

    }

    d3.selectAll(".loading-text")
        .text(loadingText + ": 100%")
    return issues
}

The current code correctly divides the rest calls into batches of 10 initially, but I am facing challenges resolving the Promise so the for-loop can progress.

My Revised Work-in-progress Function:

//Async function process rest calls in batches
function searchIssues(restCalls, batchSize, loadingText) {
    const restCallsLength = restCalls.length;
    var issues = [];
    for (var i = 0; i < restCallsLength; i += batchSize) {
        //create batch of requests
        var requests = restCalls.slice(i, i + batchSize).map(function(restCall) {
            return fetch(restCall)
                .then(function(fieldResponse) {
                    return fieldResponse.json()
                })
                .then(function(data) {
                    console.log(data)
                    response = data.issues;

                    //for each issue in response, push to issues array
                    response.forEach(function(issue) {
                        issue.fields.key = issue.key
                        issues.push(issue.fields)
                    });
                })
        })

        return Promise.resolve().then(function() {
            console.log(i)
            return Promise.all(requests);
        }).then(function() {
            d3.selectAll(".loading-text")
                .text(loadingText + ": " + parseInt((i / restCallsLength) * 100) + "%")
        });

    }

     d3.selectAll(".loading-text")
         .text(loadingText + ": 100%")
     return issues
}

My main query is, how can I ensure proper resolution of the Promise once the group of 10 rest calls is completed, allowing the iteration through the for-loop to continue smoothly?

Just as a point of reference, I attempted compiling the original function using Babel, but it failed to compile in my Maven application, hence the decision to start afresh with rewriting.

Answer №1

When it comes to pausing a for loop without using async/await, one workaround is to implement a recursive function that triggers itself after processing each batch of, say, 10 items. While this code snippet has not been tested, the concept is clear:

// Establish an asynchronous operation to handle REST calls in batches
function searchIssues(restCalls, batchSize, loadingText) {
  var restCallsLength = restCalls.length,
      issues = [],
      i = 0;

  return new Promise(function(resolve, reject) {
    (function loop() {
      if (i < restCallsLength) {
        var requests = restCalls
          .slice(i, i + batchSize)
          .map(function(restCall) {
            return fetch(restCall)
              .then(function(fieldResponse) {
                return fieldResponse.json();
              })
              .then(function(d) {
                var response = d.issues;

                // Iterate through each issue and add it to the 'issues' array
                response.forEach(issue => {
                  issue.fields.key = issue.key;
                  issues.push(issue.fields);
                });
              });
          });

        return Promise.all(requests)
          .catch(function(e) {
            console.log(`Error in processing batch ${i} - ${e}`);
          })
          .then(function() {
            // Proceed to the next iteration regardless of success or failure
            d3.selectAll(".loading-text").text(
              loadingText + ": " + parseInt((i / restCallsLength) * 100) + "%"
            );
            i += batchSize;
            loop();
          });
      } else {
        // Finish loading process and display completion as 100%
        d3.selectAll(".loading-text").text(loadingText + ": 100%");
        resolve(issues); // Resolve the main promise
      }
    })();
  });
}

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 are the potential causes of an asynchronous error in a WebGLRenderingContext?

While running an animation loop, I encountered a peculiar error message that reads... GL ERROR :GL_INVALID_OPERATION : glDrawElements: Source and destination textures of the draw are the same. This error seems to occur randomly after 2 or 3 animation fr ...

I am experiencing an issue with my Node.js query, as it is not successfully adding a user to my database using

I'm currently working on developing an API using Node.JS, express, and MySQL with the Sequelize ORM. I wanted to do this project properly without relying on the CLI for every task. However, I've encountered a problem where my API fails to create ...

Challenges with ExpressJS 4 middleware

Trying to grasp the concept of middleware in ExpressJS 4 has been quite a challenge for me. As far as I understand, middleware are applied based on the order they are declared and can be "bound" at different levels. My current focus is on binding a middl ...

Seeking advice on Javascript prototypes - how can I execute a function within a prototype without using "this"?

let Human = function (userName, userAge) { this.userName = userName; this.userAge = userAge; }; Human.prototype.sampleProto = function () { console.log(this.userName + " == " + this.userAge); ...

Verify if the input field is devoid of any content or not

I am planning to create a validation form using Vanilla JavaScript. However, I have encountered an issue. Specifically, I want to validate the 'entername' field first. If the user does not enter any letters in it, I would like to display the mess ...

Strategies for increasing a value within an asynchronous function

I'm facing an issue with incrementing the variable loopVal inside a promise. I've tried to increment it without success. Any ideas on how to make this work? const hi = function(delay) { let loopVal = 1; return new Promise((resolve, reject) ...

How AngularFire automatically adds back a removed item in a Firebase array

I have been working on a way to remove an item from my $firebaseArray called "boxes". Here is the "remove" function: function remove(boxJson) { return boxes.$remove(boxJson); } Although it gets removed, I noticed that it immediately reappea ...

Enhance your Vue router's scroll behavior with tips on navigating route values

I am working on a route that includes various parameters and queries: For the parent route: path: "/:locale(en|jp)?" And for the products route: path: 'products/:category/:page?' The query in product may include: { q: search string for filter ...

Updating a particular element within nested arrays: best practices

I have developed a data table containing student records using material UI. Each row represents a different student array with a fee verification button. My goal is to change the fee status when the button is clicked for a specific student, but currently t ...

Reasons for implementing attribute normalization in AngularJS

I am currently in the process of learning AngularJS through w3schools. The website offers a helpful example on creating custom directives, which can be found at Custom Directives. <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/ang ...

The browser failed to display the SVG image, and the console log indicated that the promise was rejected, with the message "false."

I'm struggling to understand why my SVG isn't showing up on the screen. The console log is displaying "false," which I believe indicates that a promise was rejected Here is the TypeScript file I am working with: export class PieChartComponent im ...

"Select2 dropdown search bar vanishing act: The hunt for results comes up empty

Currently, I am dealing with a scenario involving two modals, each containing a select2 search dropdown. An issue has arisen where selecting modal one filters the dropdown data effectively. However, upon selecting modal two, although the data is filtered i ...

What is the most effective approach to integrating socket.io as a submodule into the ExpressJS framework?

In my current project, I am working on developing an application using ExpressJs and following the submodule architecture recommended by tjholowaychuk. Furthermore, I also want to incorporate real-time socket interactions into the app by integrating socke ...

Executing multiple AJAX calls at the same time in PHP

I have a puzzling question that I can't seem to easily solve the behavior of this situation There are two ajax call functions in my code: execCommand() : used for executing shell commands through PHP shell_exec('ping 127.0.0.1 > ../var/l ...

Issue encountered during installation of the robotjs npm package

Would appreciate any assistance with troubleshooting this issue. I've been grappling with it for 3 days, putting in countless hours of effort. The problem arises when attempting to install the robotjs npm package, as errors keep popping up. I've ...

Retrieving multiple selected row values using an ASP Repeater

Within my repeater, I have three values bound: a visible "User Name" column, a visible "Business" column, and a hidden field called "UserId". My goal is to implement the following functionality: when a row is clicked, it should highlight in a different c ...

How come my HTML form keeps refreshing instead of displaying an alert after submission, even though I've included onsubmit="return false"? Additionally, it seems to be throwing an error

Why is this basic HTML and JavaScript code not functioning properly? Instead of alerting once the form is submitted, it refreshes the page and throws an error. It has also been reported to sometimes throw a CORS error when using 'module' as scri ...

What is the best way to categorize elements in an array of objects with varying sizes based on two distinct properties in JavaScript?

I am faced with a scenario where I have two distinct arrays of objects obtained from an aggregate function due to using two different collections. Although I attempted to utilize the map function as outlined here, it proved unsuccessful in resolving my is ...

Adjust the color of the navbar only after a user scrolls, with a slight delay rather than

My code changes the navbar colors when I scroll (200ms). However, I would like the changes to occur when I am slightly above the next section, not immediately. In other words, what adjustments should I make to change the color in the next section and not ...

Populate Vue components dynamically without the need for additional frameworks like Nuxt in Vue3

My goal is to develop a checksheet application using Vue, where the tasks are specified in an excel file. ===== To start, task A needs to be completed. Followed by task B. and so on... ===== I am considering creating a CheckItem.vue component fo ...