解析后台作业查询迭代在获取数据之前返回

时间:2015-05-30 00:44:03

标签: parse-platform jobs cloud-code

我正在尝试对我的一些Parse数据运行一些统计数据,以便了解到目前为止的使用统计信息。

基本上我是基于创建它们的日期对属性进行排序,并尝试遍历每个属性以查看创建它的用户是否是该区域的新用户,以及它们是否是可结算用户(已输入付款信息的人)。用户可以是多个邮政编码的客户,并且可以在创建帐户后随时成为新邮政编码的客户,这使我收集此数据的方式变得复杂。对不起凌乱的代码,我试着添加一些评论以显示正在发生的事情。搜索“// HERE”以查看问题的开始位置。 (下面的更新代码)

Parse.Cloud.job("runStatistics", function(request, status)
{
    Parse.Cloud.useMasterKey();
    // These are variables I'm outputting to see the behaviour of this background job.  fetchedProperties and 
    // fetchAttempts are both the same, and equal to the total number of properties, but the rest all remain 0.
    var failedUsers = 0;
    var successfulUsers = 0;
    var skippedUsers = 0;
    var nonSkippedUsers = 0;
    var propertyFetchErrors = 0;
    var fetchedProperties = 0;
    var fetchAttempts = 0;
    var totalProperties;

    // These are associative arrays  or arrays (key being the zip code) where I store whether or not someone 
    // is already a user for a zip code, or if they have requested a cut (purchasing from our app)
    var usersForZIPCode = {};
    var cutsForZIPCode = {};

    //I create a statistics object for each zip code for each week
    var Statistics = Parse.Object.extend("Statistics", 
    {
        initialize: function(attrs, options)
        {
            this.newUsers = 0;
            this.newBillableUsers = 0;
            this.firstCut = 0;
            this.additionalCuts = 0;
            this.numCuts = 0;
            this.totalBillableUsers = 0;
        }
    });
    var statisticsArray = new Array();
    var i = 0;
    for( i = 0; i < serviceableZIPCodesArray.length; i++ ) //ServiceableZIPCodesArray is an array of the zip codes we currently service, defined elsewhere.
    {
        usersForZIPCode[ serviceableZIPCodesArray[i] ] = new Array(); 
        cutsForZIPCode[ serviceableZIPCodesArray[i] ] = new Array();
        var j = 1;
        for( j = 1; j < 4; j++ )
        {
            var statistics = new Statistics();
            statistics.set("zipCode", serviceableZIPCodesArray[i]);
            statistics.set("week", j);
            statisticsArray.push(statistics);
        }
    }

    //Here I set up the property query. I have less than 1000 properties at the moment.
    var propertyQuery = new Parse.Query("Property");
    propertyQuery.limit(1000);
    propertyQuery.ascending("createdAt");
    propertyQuery.find( 
    {
        success: function(results)
        {
            totalProperties = results.length; //This is properly set
            for( var x = 0; x < results.length; x++)
            {
                var property = results[x];
                fetchAttempts++; //This is hit every time
                property.fetch( //HERE
                {
                    success: function(property)
                    {
                        fetchedProperties++; //This is never called, always returns 0.
                        dateCreated = property.createdAt;
                        var weekNum;
                        var newUserBool = false;
                        var billableUserBool = false;
                        var ZIPIndex = serviceableZIPCodesArray.indexOf( property.get("zip") );
                        if( serviceableZIPCodesArray.indexOf( property.get("zip") ) == -1 )
                        {
                            skippedUsers++; //this is never called, always returns 0
                        } 
                        else
                        {
                            nonSkippedUsers++; //this is never called, always returns 0

                            //These look a bit messy. Basically I'm using the current property's zip code as a key to get an
                            //array of users that already have properties in that zip code, so I don't count them twice
                            if( usersForZIPCode[ property.get("zip") ].indexOf( property.get("User") ) == -1 )
                            {
                                usersForZIPCode[ property.get("zip") ].push( property.get("User") );
                                newUserBool = true; //If the index was -1, they are a new user.
                            }
                            property.get("User").fetch( //User is a pointer to a User object that owns this property
                            {
                                success: function(user)
                                {
                                    successfulUsers++; //this is never called, always returns 0
                                   if( user.has(/* removing this in case it's a security issue*/) ) billableUserBool = true; 
                                   //This tells us which week the property was created: 1, 2, or 3.
                                   if( dateCreated.getDate() < 18 ) weekNum = 1; 
                                    else if( dateCreated.getDate() < 25 ) weekNum = 2;
                                    else weekNum = 3;
                                    //Based on which week the object was created, we update the statistics object
                                    switch(weekNum)
                                    {
                                        case 1:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        case 2:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        case 3:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        default:
                                    }

                                },
                                error: function(user, error)
                                {
                                    failedUsers++; //this is never called, always returns 0
                                }
                            }).then(
                            function()
                            {
                                    successfulUsers++;
                            },
                            function(error)
                            {
                                    failedUsers++; //this is never called, always returns 0
                            });
                        }
                    },
                    error: function(property, error)
                    {
                        propertyFetchErrors++; //this is never called, always returns 0
                    }
                }).then(
                function(property)
                {
                    fetchedProperties++; //this is never called, always returns 0
                },
                function(error)
                {
                    propertyFetchErrors++; //this is never called, always returns 0
                });
            }
        },
        error: function(results, error)
        {
            status.error("Uh oh, something went wrong with the query" + error); 
        }
    }).then(
        function()
        {
            console.log("failed users = " + failedUsers);
            console.log("successful users = " + successfulUsers);
            console.log("skipped users = " + skippedUsers);
            console.log("nonSkipped users = " + nonSkippedUsers);
            console.log("total properties = " + totalProperties);
            console.log("fetch attempts = " + fetchAttempts);
            console.log("property fetch errors = " + propertyFetchErrors);
            console.log("fetched properties = " + fetchedProperties);
            Parse.Object.saveAll(statisticsArray).then( 
            function()
            {
                status.success("created statistics objects");
            }, function(error)
            {
                status.error("Uh oh, something went wrong while saving." + error);
            });
        },
        function(error)
        {
            status.error("something went wrong with the property query" + error);
    });
});

对不起它太长而且很乱,如果你认为我应该更新这个没有大部分无法达到的代码,请告诉我。我只记得阅读一些关于promises的文档,说明当你在返回promise时调用promise的函数时,它们会有不同的行为。我认为返回一个promise的内部函数必须先完成,所以我会在这里受到保护,但显然我错了,因为我的提取永远不会被调用。

我感谢任何帮助!我已经被困在这几个小时了。

编辑 - 我已将代码更改为仅使用promises,而不是混合使用回调和承诺。事实证明我不需要再次获取属性,因为查询已经获取它。我必须有一个拼写错误的变量名称,或之前给我一个空对象的东西。

但是,现在我的问题是没有提取用户。它基本上和以前一样,只是在一个不同的地方,因为我实际上不需要做原始的提取。这是我更新的代码:

Parse.Cloud.job("runStatistics", function(request, status)
{
    Parse.Cloud.useMasterKey();
    // These are variables I'm outputting to see the behaviour of this background job.  fetchedProperties and 
    // fetchAttempts are both the same, and equal to the total number of properties, but the rest all remain 0.
    var failedUsers = 0;
    var successfulUsers = 0;
    var skippedUsers = 0;
    var nonSkippedUsers = 0;
    var propertyFetchErrors = 0;
    var fetchedProperties = 0;
    var fetchAttempts = 0;
    var totalProperties;

    // These are associative arrays  or arrays (key being the zip code) where I store whether or not someone 
    // is already a user for a zip code, or if they have requested a cut (purchasing from our app)
    var usersForZIPCode = {};
    var cutsForZIPCode = {};

    //I create a statistics object for each zip code for each week
    var Statistics = Parse.Object.extend("Statistics", 
    {
        initialize: function(attrs, options)
        {
            this.newUsers = 0;
            this.newBillableUsers = 0;
            this.firstCut = 0;
            this.additionalCuts = 0;
            this.numCuts = 0;
            this.totalBillableUsers = 0;
        }
    });
    var statisticsArray = new Array();
    var i = 0;
    for( i = 0; i < serviceableZIPCodesArray.length; i++ ) //ServiceableZIPCodesArray is an array of the zip codes we currently service, defined elsewhere.
    {
        usersForZIPCode[ serviceableZIPCodesArray[i] ] = new Array(); 
        cutsForZIPCode[ serviceableZIPCodesArray[i] ] = new Array();
        var j = 1;
        for( j = 1; j < 4; j++ )
        {
            var statistics = new Statistics();
            statistics.set("zipCode", serviceableZIPCodesArray[i]);
            statistics.set("week", j);
            statisticsArray.push(statistics);
        }
    }

    //Here I set up the property query. I have less than 1000 properties at the moment.
    var propertyQuery = new Parse.Query("Property");
    propertyQuery.limit(1000);
    propertyQuery.ascending("createdAt");
    propertyQuery.find().then( 
        function(results)
        {
            totalProperties = results.length; //This is properly set
            for( var x = 0; x < results.length; x++)
            {
                var property = results[x];
                fetchAttempts++; //This is hit every time
                        fetchedProperties++; //obviously, this now == fetchAttemps
                        dateCreated = property.createdAt;
                        var weekNum;
                        var newUserBool = false;
                        var billableUserBool = false;
                        var ZIPIndex = serviceableZIPCodesArray.indexOf( property.get("zip") );
                        if( serviceableZIPCodesArray.indexOf( property.get("zip") ) == -1 )
                        {
                            skippedUsers++; //this gets set.
                        } 
                        else
                        {
                            nonSkippedUsers++; //this gets set

                            //These look a bit messy. Basically I'm using the current property's zip code as a key to get an
                            //array of users that already have properties in that zip code, so I don't count them twice
                            if( usersForZIPCode[ property.get("zip") ].indexOf( property.get("User") ) == -1 )
                            {
                                usersForZIPCode[ property.get("zip") ].push( property.get("User") );
                                newUserBool = true; //If the index was -1, they are a new user.
                            }
                            property.get("User").fetch().then( //User is a pointer to a User object that owns this property
                            function(user)
                            {
                                    successfulUsers++;
                                    if( user.has(/* removing this in case it's a security issue*/) ) billableUserBool = true; 
                                   //This tells us which week the property was created: 1, 2, or 3.
                                   if( dateCreated.getDate() < 18 ) weekNum = 1; 
                                    else if( dateCreated.getDate() < 25 ) weekNum = 2;
                                    else weekNum = 3;
                                    //Based on which week the object was created, we update the statistics object
                                    switch(weekNum)
                                    {
                                        case 1:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        case 2:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("totalBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 1 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        case 3:
                                            if( newUserBool )
                                            {
                                                if( billableUserBool )
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newBillableUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newUsers");
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("totalBillableUsers");
                                                }
                                                else
                                                {
                                                    statisticsArray[ ZIPIndex*3 + 2 ].increment("newUsers");
                                                }
                                            }
                                            break;
                                        default:
                                    }
                            },
                            function(error)
                            {
                                    failedUsers++; //this is never called, always returns 0
                            });
                        }
            }
        },
        function(results, error)
        {
            status.error("Uh oh, something went wrong with the query" + error); 
        }
    ).then(
        function()
        {
            console.log("failed users = " + failedUsers);
            console.log("successful users = " + successfulUsers);
            console.log("skipped users = " + skippedUsers);
            console.log("nonSkipped users = " + nonSkippedUsers);
            console.log("total properties = " + totalProperties);
            console.log("fetch attempts = " + fetchAttempts);
            console.log("property fetch errors = " + propertyFetchErrors);
            console.log("fetched properties = " + fetchedProperties);
            Parse.Object.saveAll(statisticsArray).then( 
            function()
            {
                status.success("created statistics objects");
            }, function(error)
            {
                status.error("Uh oh, something went wrong while saving." + error);
            });
        },
        function(error)
        {
            status.error("something went wrong with the property query" + error);
    });
});

1 个答案:

答案 0 :(得分:1)

不要将promises与回调混合,选择2种方法中的1种并坚持使用。混合和匹配通常意味着某些内容会被删除,并且您的函数会在不调用status处理程序的情况下提前退出。

使用promises将帮助您破解代码,以便更容易理解。

在运行fetch之后,您不需要运行find,因为查询应返回每个对象的所有列值。

以后使用时,您可能需要考虑使用.each代替.find

使用promises时,你需要链接它们并返回嵌套的promises:

query.find().then(function(x) {
    ... // basic logic
    return object.save(); // return when creating a promise
}).then( function(y) {
    ...
}) ...

注意,您可以链接save,但需要返回承诺链的“头部”。