嵌套的 Javascript 异步函数和回调

标签 javascript asynchronous parse-platform

部分是 parse.com 问题,他们的 API 是独一无二的。但是,我遇到的问题有点小,因为我是 javascript 的新手,并没有完全理解它。

我的代码在我想做的事情上得到了很好的评论!有一段代码全部大写注释,这是我遇到问题的部分。

任何关于如何在我的代码中控制 javascript 异步调用的见解都会很有用。

代码

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");

        }
    });
});

我发现了一些关于这个 here 的帖子但我没有犯一个安装查询的错误。我为循环中的每个迭代制作一个

主要问题是:

 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");
                            }

没有执行。没有错误日志没有成功日志只是没有被调用。

我觉得这与异步性质有关。进程终止,调用永远不会被回调。

最佳答案

我认为您是对的,问题的根源似乎是回调。在您突出显示的 for 循环中,您不会等待那些 find() 调用完成后再继续。之后的Push也是如此。我已经大大简化了您的代码来说明发生了什么。简而言之,response.success() 在异步完成之前被调用,因此您永远不会看到回调。

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() {}
    });
});

我建议使用 Promises稍微简化一下。这看起来像这样:

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);
});

关于嵌套的 Javascript 异步函数和回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23488184/

相关文章:

javascript - 如何将 PHP Instagram 签名与 AJAX 结合使用?

javascript - 如何将对象(及其属性/值)打印到 DOM

javascript - NVD3散点图每个节点如何添加onclick事件

javascript - 如何正确处理 Promise 链中的错误?

swift - Facebook 登录 Xcode 6.4 swift 出错

javascript - 在搜索框中输入并重定向到另一个页面

c# - 在C#中创建多个TCP连接然后等待数据

javascript - Playfab - 引用错误 : "Promise" is not defined

ios - 检查提供的字段是否为 nil、Parse、Swift

javascript - 带有 parse.com 登录的 AngularJS Controller