3

I want to create a array containing objects, and I'm using Parse to query all the data.

However, the for loop which loops over the results doesn't does that in the correct order but randomly loops over the data. If I log i each iteration, the logs show different results every time.

Here is my code:

for (var i = 0; i < results.length; i++)
{
Parse.Cloud.useMasterKey();
// retrieve params
var objectid = results[i];
var self = request.params.userid;

// start query
var Payment = Parse.Object.extend("Payments");
var query = new Parse.Query(Payment);

query.get(objectid, {

    success: function (payment) {

        // get all the correct variables
        var from_user_id = payment.get("from_user_id");
        var to_user_id = payment.get("to_user_id");
        var amount = payment.get("amount");
        var createdAt = payment.updatedAt;
        var note = payment.get("note");
        var img = payment.get("photo");
        var location = payment.get("location");
        var status = payment.get("status");

        var fromquery = new Parse.Query(Parse.User);
        fromquery.get(from_user_id, {

            success: function(userObject) {

                var fromusername = userObject.get("name");

                var currency = userObject.get("currency");

                var toquery = new Parse.Query(Parse.User);
                toquery.get(to_user_id, {

                    success: function(touser)
                    {

                        var tousername = touser.get("name");

                        if(tousername !== null || tousername !== "")
                        {
                            sendArray(tousername);
                        }

                    },
                    error: function(touser, error)
                    {

                        var tousername = to_user_id;

                        if(tousername !== null || tousername !== "")
                        {
                            sendArray(tousername);
                        }

                    }

                });

                function sendArray(tousername) {

                    var array = new Array();

                    // create the time and date
                    var day = createdAt.getDate();
                    var year = createdAt.getFullYear();
                    var month = createdAt.getMonth();
                    var hour = createdAt.getHours();

                    var minutes = createdAt.getMinutes();

                    // create the timestamp
                    var time = "" + hour + ":" + minutes;
                    var date = "" + day + " " + month + " " + year;

                    var associativeArray = {};

                    if(self == from_user_id)
                    {
                        fromusername = "self";
                    }
                    if(self == to_user_id)
                    {
                        tousername = "self";
                    }

                    associativeArray["from"] = fromusername;
                    associativeArray["to"] = tousername;
                    associativeArray["amount"] = amount;
                    associativeArray["currency"] = currency;
                    associativeArray["date"] = date;
                    associativeArray["time"] = time;
                    associativeArray["status"] = status;

                    if(note == "" || note == null)
                    {
                        associativeArray["note"] = null;
                    }
                    else
                    {
                        associativeArray["note"] = note;
                    }

                    if(img == "" || img == null)
                    {
                        associativeArray["img"] = null;
                    }
                    else
                    {
                        associativeArray["img"] = img;
                    }

                    if(location == "" || location == null)
                    {
                        associativeArray["location"] = null;
                    }
                    else
                    {
                        associativeArray["location"] = location;
                    }

                    array[i] = associativeArray;

                    if((i + 1) == results.length)
                    {
                        response.success(array);
                    }

            },
            error: function(userObject, error)
            {
                response.error(106);
            }

        });

    },
    error: function(payment, error) {

        response.error(125);

    }

});
}

But the i var is always set to seven, so the associative arrays are appended at array[7] instead of the correct i (like 1,2,3,4,5)

The reason that this is so important is because I want to order the payment chronologically (which I have done in the query providing the results).

What can I do to solve this issue?

Andre
  • 893
  • 2
  • 9
  • 30
  • 1
    Read up on how closures work in javascript, that is the reason why i is always 7. [How do javascript closures work](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) – Matt R Aug 15 '14 at 15:21
  • @MattR thanks for your help. I however still don't understand why `i` is always 7. Could you point me in the right direction? – Andre Aug 15 '14 at 15:49

1 Answers1

2

Success is a callback that happens at a later point in time. So what happens is, the for loop runs 7 times and calls parse 7 times. Then after it has run each of parse success calls will be executed, they look at i which is now at 7.

A simple way to fix this is to wrap the whole thing in an immediate function and create a new closure for i. Something like this

for(var i = 0; i < results.length; i++){
   function(iClosure) {
      //rest of code goes here, replace i's with iClosure
   }(i);
}

Now what will happen is that each success function will have access to it's own iClosure variable and they will be set to the value of i at the point they were created in the loop.

Matt R
  • 724
  • 5
  • 14