Вопрос

This is a parse.com question partly and their API is unique. However, the problem I am having is a little bit because I am new to javascript and dont fully undrestand it.

My code is very well commented on what I am suppose to do! There is a section of code that is commented in all caps, that is the section I am having trouble with.

Any insight to how to control javascripts async calls in my code will be useful.

CODE

Parse.Cloud.define("StartSession", function(request, response) {
    var query =new Parse.Query("User"); // search the User class
    query.containedIn("username", request.params.myArray); //get the users that are in my array
    query.find({
        success: function(results) { // if found do this
            // Didn't find a keyword to match tags so create new keyword

            //result is all the users that are in this session to be created.
            var Session = Parse.Object.extend("Session"); // create a session objsect
            var mySession = new Session();  // create an instance of the session
            console.log("the log is");
            var users = []; // all the users
            var deviceID = []; // their corsponding ids
            users.push(request.params.user); // add an extra item to the users array that is being passed into this funciton on the original call

            for (var i = 0; i <= results.length - 1; i++) { // iterate all of the results returned from the find
                users.push(results[i].get("username")); // get their username attribute and add it to the users array
                deviceID.push(results[i].get("installID")); // get their associated installID and add it to deviceID
            };
            // users.splice(users.indexOf(request.params.user), 1);
            mySession.set("users", users); // put all of the supplied users found into this session
            mySession.set("owner", request.params.user) // set the owner of the session. This was passed in

            console.log(results);
            var installs = new Parse.Query(Parse.Installation); // get the installs class

            mySession.save(null, { // save the session
                success: function(gameScore) { //if successful go on
                    // Execute any logic that should take place after the object is saved.
                    console.log("getting"); // logging
                    for (var i = deviceID.length - 1; i >= 0; i--) { //iterate all of the deviceIDs from the above
                    var sessionID = mySession.id; // get the session id for the session that was just created

                        installs.contains("objectid", deviceID[i]); // make a search for the installs class
                        installs.find({ // find given the above search
                            success: function(myResults){ // if success
                                console.log("getting2"); // log something
                                var tempChannels = myResults.get('channels'); // get the given users channels list and save it into an array
                                console.log(myResults); // log something
                                tempChannels.push(sessionID); // add the new sessionId to their list of channels
                                myResults.set("channels", tempChannels); // put back the newly modified array which should be a list of channels
                            }, // THE SUCCESS CODE ABOVE IS NOT WORKING OR DOING ANYTHING. CHANNEL IS NOT CHANGING NOR IS ANYTHING GETTING LOGGED
                            error: function(error){ // NOR IS THE ERROR CODE
                                console.log("getting 3")
                                console.log("asD");
                            }
                        });
                        // var channels = deviceID[i].get("channels");
                        // console.log("adding a channel for "+deviceID[i]);
                        // channels.push(sessionID);
                        // deviceID[i].set("channels", channels);
                    }; //THE REST IS UNIMPORTANT FOR THIS QUESTI

                    var targets = new Parse.Query(Parse.Installation);
                    console.log("check point 1 "+sessionID);
                    //targets.equalTo('deviceType', ['android']);
                    targets.contains("channels", sessionID)
                    if (targets.length > 0) {console.log("There are more than one recipiants for this")};
                    console.log("check point 2");
                    console.log(targets.length);
                    Parse.Push.send({
                        where: targets,
                        data: {
                            alert: "test",
                        }
                    }, {
                        success: function() {
                            // Do something on success
                            console.log("Was able to send notifications");
                            console.log("check point 3");

                        },
                        error: function() {
                            // Do something on error
                            console.log("Error sending the notifications");
                            console.log("check point 4");

                        }
                    });
                    response.success(users);

                },
                error: function(gameScore, error) {
                    // Execute any logic that should take place if the save fails.
                    // error is a Parse.Error with an error code and description.
                    response.success("ERROR");
                    console.log("check point 5");

                }
            });                 
        },
        error: function() {
            response.error("Found nothing");
            console.log("check point 6");

        }
    });
});

I found a few posts regarding the same sort of this here but I did not make the mistake of having one installs query. I make one for each iteration in the loop

The main problem is that:

 for (var i = deviceID.length - 1; i >= 0; i--) { //iterate all of the deviceIDs from the above
                    var sessionID = mySession.id; // get the session id for the session that was just created

                        installs.contains("objectid", deviceID[i]); // make a search for the installs class
                        installs.find({ // find given the above search
                            success: function(myResults){ // if success
                                console.log("getting2"); // log something
                                var tempChannels = myResults.get('channels'); // get the given users channels list and save it into an array
                                console.log(myResults); // log something
                                tempChannels.push(sessionID); // add the new sessionId to their list of channels
                                myResults.set("channels", tempChannels); // put back the newly modified array which should be a list of channels
                            }, // THE SUCCESS CODE ABOVE IS NOT WORKING OR DOING ANYTHING. CHANNEL IS NOT CHANGING NOR IS ANYTHING GETTING LOGGED
                            error: function(error){ // NOR IS THE ERROR CODE
                                console.log("getting 3")
                                console.log("asD");
                            }

which is not executing. No error logs no success logs just doesnt get called.

I feel like it has to do with the async nature. The process terminates and the calls never get called back.

Это было полезно?

Решение

I think you're right that the source of the issue appears to be due to the callbacks. In the for loop you highlighted, you're not waiting for those find() calls to complete before continuing. The same is true for the Push after that. I've greatly simplified your code to illustrate what's happening. In short, response.success() is called before the asyncs finish so you never see the callbacks.

Parse.Cloud.define("StartSession", function(request, response) {
    query.find({
        success: function(results) {
            mySession.save(null, {
                success: function(gameScore) {
                    for (var i = deviceID.length - 1; i >= 0; i--) {
                        installs.find();    // not waiting for this
                    };

                    Parse.Push.send(); // not waiting for this

                    // called before the async's fire so no callbacks happen
                    response.success(users);
                },
                error: function(gameScore, error) {}
            });                 
        },
        error: function() {}
    });
});

I'd suggest using Promises to simplify things a bit. That would look something like this:

Parse.Cloud.define("StartSession", function(request, response) {
    query.find().then(function(results) {
        return mySession.save();
    }).then(function(mySession) {
        var installQueries = [];

        for (var i = deviceID.length - 1; i >= 0; i--) {
            installQueries.push(installs.find());    // not waiting for this
        };

        // wait for all the install queries to finish
        return Parse.Promise.when(installQueries);
    }).then(function() {
        return Parse.Push.send();
    }).then(response.success, response.error);
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top