Conclude the execution of promises after a for loop

I'm looking to enhance my code by ensuring that it waits for the asynchronous query called prom to finish before resetting the array and restarting the first for loop. This way, the array will be cleared before the loop begins again.

items = [];
var promises = [];
    for (var i = 0; i < userArray.length; i++) {

        items.length = 0;
        for (var i2 = 0; i2 < test.length; i2++) {

           var UserFavourite = Parse.Object.extend("UserFavourite");
            var queryUserFav = new Parse.Query(UserFavourite);
            queryUserFav.equalTo('item', test[i2].get('item'));
            queryUserFav.equalTo('school', test[i2].get('school'));
            queryUserFav.equalTo('user1', userArray[i])
            var prom = queryUserFav.find().then(function(res) {

                    for (var i3 = 0; i3 < res.length; i3++){
                        var item = res[i3];
                        var itemName = item.get('item');
                        items.push(itemName);
                        console.log(items)

                    }
                    return items;

            });
            promises.push(prom);

        }
        //return Parse.Promise.when.apply(Parse.Promise, promises); I have tried it here but
        // this just stops the first for loop after its first loop

    }
    return Parse.Promise.when.apply(Parse.Promise, promises);

Answer №1

To achieve your goal, you need to create a series of promises, each corresponding to an item in an array.

It would be convenient if JavaScript had a feature similar to .NET's await keyword, allowing you to use:

 await Parse.Promise.when(promises)

This would enable the promise code to execute and then resume running any code after the await. Unfortunately, JavaScript does not offer this functionality.


Another strategy involves maintaining an index variable. After processing each set of queries, increment the index to move on to the next set of values.

 function parseForUser(user) {
      var promises = [];
      for (var i2 = 0; i2 < test.length; i2++) {
        var items = [];
        var UserFavourite = Parse.Object.extend("UserFavourite");
        var queryUserFav = new Parse.Query(UserFavourite);
        queryUserFav.equalTo('item', test[i2].get('item'));
        queryUserFav.equalTo('school', test[i2].get('school'));
        queryUserFav.equalTo('user1', user)
        var prom = queryUserFav.find().then(function(res) {
                for (var i3 = 0; i3 < res.length; i3++){
                    var item = res[i3];
                    var itemName = item.get('item');
                    items.push(itemName);
                    console.log(items)

                }
                return items;
        });
        promises.push(prom);
      }
      return Parse.Promise.when(promises);

 }


 function parseUserArray(userArray) {
     var returnPromise = new Parse.Promise(); // Do you have to call it via new? 
                                              //The documentation isn't clear.
     var index = 0;
     var doNext = function() {
         if(index < userArray.length) {
            var promise = parseForUser(userArray[index++]);
            promise.done(doNext);
         } else {
             returnPromise.resolve(); 
         }
     }
     doNext();
     return returnPromise;
 }

 var parseUserArrayPromise = parseUserArray(userArray);

Answer №2

Just my two cents...

In this approach, we deviate slightly from @AndrewShepherd's method by leveraging the promise returned by asyncProcessUser() in two ways.

  • Firstly, for managing the flow - ensuring the asynchronous sequencing of the inner loop.
  • Secondly, for providing an array of results that contribute to the final array, eliminating the necessity for an outer promises array.
function parseUserArray(userArray, test) {

    // This function, now portrayed as a .map(), processes a single user asynchronously against all test items,
    // returning a promise of an array of results.
    function asyncProcessUser(user) {
        return Parse.Promise.when(test.map(function(dataItem) {
            return (new Parse.Query(Parse.Object.extend("UserFavourite")))
                .equalTo('item', dataItem.get('item'))
                .equalTo('school', dataItem.get('school'))
                .equalTo('user1', user)
                .find().then(function(res) {
                    return res.map(function(r) {
                        return r.get('item');
                    });
                });
        })).then(function() {
            return Array.prototype.slice.apply(arguments).reduce(function(arr, arr_) {
                return arr.concat(arr_);
            }, []);
        });
    }

    // This section, converted to a .reduce(), executes a series of asynchronous tasks (previously in the inner loop).
    // `userArray.reduce(...)` yields a promise of an array of objects returned by `r.get('item')` above.
    return userArray.reduce( function(p, user) {
        return p.then(function(arr) {
            return asyncProcessUser(user).then(function(arr_) {
                return arr.concat(arr_);
            });
        });
    }, Parse.Promise.as([]) );//† "returns a new promise that is resolved with a given value".
}

† : More insights on Parse.Promise.as()

When stripped of the comments, the code becomes more concise.

The principle is exemplified here. Regardless of the jQuery promises in the demo, the core concept remains.

Answer №3

Utilize this

function scanForUser(user) {
      var promises = [];
      for (var i2 = 0; i2 < test.length; i2++) {
        var items = [];
        var UserFavorite = Parse.Object.extend("UserFavorite");
        var queryUserFav = new Parse.Query(UserFavorite);
        queryUserFav.equalTo('item', test[i2].get('item'));
        queryUserFav.equalTo('school', test[i2].get('school'));
        queryUserFav.equalTo('user1', user)
        var prom = queryUserFav.find().then(function(res) {
                for (var i3 = 0; i3 < res.length; i3++){
                    var item = res[i3];
                    var itemName = item.get('item');
                    items.push(itemName);
                    console.log(items)

                }
                return items;
        });
        promises.push(prom);
      }
      return Parse.Promise.when(promises);

 }


 function scanUserArray(userArray) {
     var returnPromise = new Parse.Promise(); // Do you have to call it via new? 
                                              //The documentation isn't clear.
     var index = 0;
     var doNext = function() {
         if(index < userArray.length) {
            var promise = scanForUser(userArray[index++]);
            promise.done(doNext);
         } else {
             returnPromise.resolve(); 
         }
     }
     doNext();
     return returnPromise;
 }

Simply copy and paste

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

Angular often uses the JavaScript pattern for development

After completing an AngularJS tutorial on http://www.tutorialspoint.com/angularjs/angularjs_services.htm, I found myself puzzled by the method used in the CalcService service. It seemed unclear whether Angular was using revealing prototype or a different ...

Deliver an assured result to a variable within the angular.extend() function

Can someone provide guidance on how to set myVar to a value returned from an asynchronous service method in the following example? angular.extend(this, { myVar: (function() { getVal(); })() }); function getVal() { var d = $q.defer(); ...

How can we use the nth-of-type selector to target a set of eight elements in a

I am trying to style a group of divs in such a way that every set of eight elements will have the same left positioning. Rather than just styling every eighth element individually, I want to apply the styling to groups of eight elements at once. However, ...

Flask caches JSON files automatically

I am currently working on a visualization app using js and python. The functionality of my app is as follows: There is a textbox in the browser where I input an URL The URL is then sent to Python via Flask In Python, the URL is processed to create ...

Tips for eliminating repeated values in a textbox

<script> $("#filter").on("shown.bs.popover",function(){ $(".popover-content input[type=checkbox]").on("click",function(){ if(this.checked) { this.setAttribute("checked","checked"); } else { ...

Implementing pagination in a table with the help of jQuery

I've been working on this code for the past few days and I'm struggling to find a solution that meets my requirements. What I need is pagination within a specific section of a table, with the following actions/events: When clicking previous o ...

What could be causing my Rest API request to malfunction?

Currently, I am working on a Pokedex website as part of my practice to enhance my skills in using API Rest. However, I have encountered some issues with the functionality. When users first enter the site, the API is being called twice unnecessarily. Additi ...

Unable to fetch Rails response through Ajax

Whenever I make a post request from my phonegap app (using ajax in javascript) to my rails server, the post goes through successfully. However, I do not receive any response from the server which ultimately leads to failure. It's puzzling why I'm ...

Navigating arrays containing arrays/objects and updating properties in Angular using loops

My challenge involves an array containing arrays and objects. Within a function, I am attempting to assign a value to a specific property (for example, setting 'call' of $scope.companies[0].users to the value selected in a checkbox). Despite my r ...

Ensuring a Fixed Delta Tooltip in lightweight-charts is essential for maintaining a seamless

I have implemented lightweight-charts to present a chart using mock data. I am looking to establish a fixed Delta Tooltip on the chart when the page loads, with predetermined start and end dates that are specified as input. Furthermore, I aim to restrict t ...

Communication between Nodemailer and Mailgun

I keep encountering an authentication issue while trying to use Nodemailer with Mailgun. I followed the Nodemailer documentation which states compatibility with Mailgun SMTP, but unfortunately, I am consistently facing this error when executing my applicat ...

Jquery Position behaving unexpectedly during initial invocation

My goal is to have the autocomplete menu open above the input box if there is not enough space below it. The code functions properly, except for the initial render. It consistently displays at the bottom in the following scenarios: 1. When starting a searc ...

Duplicate values of React object properties when using .push method within a loop

In my code, I've implemented a function called handleCreate that is responsible for taking user data and inserting it into a database. Within the loop of aliasArr.forEach(), I am sending new user instances to my database for each element in the alias ...

Creating a Json array of strings in Android is a straightforward process that involves following a few

Struggling to craft an array similar to this ["stringone","stringtwo"] for transmission to the webserver. However, attempts with a string array like String[]={"stringone","stringtwo"] yielded an odd outcome {"userids":"[Ljava.lang.String;@406fe4b8"}. What ...

Tips for resolving the 'route.search' bug in Express.js

I recently started working on a basic Express app (with Node) and I am in the initial setup phase. However, I have encountered an error that is proving to be quite challenging to resolve. Despite my attempts to search for solutions online and browse throu ...

What is the process of using AJAX, JavaScript, and HTML to submit data to a remote

I need help with sending data from an HTML page to a server. I have a JSON example below that illustrates what I want to achieve. On my HTML page, I have a question label and four options (A, B, C, D) as radio buttons. After clicking the send button, I ...

AngularJS allows a function to return an array value, which can be displayed in separate blocks on

Building a program that involves working with an AngularJS array. I need to showcase the elements of the AngularJS array, returned by a function, in an organized manner. Each element should be displayed correspondingly - for example, 'first' cont ...

The data sent within an event does not trigger reactivity

Not producing errors, just failing to function. The addition of this also has no impact. input( type="number" v-model="myData" @wheel="wheelIt($event, myData, myMethod)" ) ... methods: { wheelIt ( event, data, func ) { if ( event.deltaY ...

Guide on how to forward the response obtained from an Ajax call to a different HTML page

I am working with a mongoose database that stores data containing an individual's first and last name. The user inputs their first name into a field, triggering an ajax request sent to the file named controller.js. This file generates a JSON response ...

What prevents certain scenarios from being encapsulated within a try/catch block?

Just attempted to handle ENOENT by using a naive approach like this: try { res.sendFile(path); } catch (e) { if (e.code === 'ENOENT') { res.send('placeholder'); } else { throw e; } } Unfortunately, this method is ineffectiv ...