我想對我的一些解析數據運行一些統計信息,以獲取到目前爲止的使用情況統計信息。解析後臺作業查詢迭代在獲取數據之前返回
基本上,我基於它們被創建的日期對屬性進行排序,並嘗試遍歷每個屬性以查看創建它的用戶是否是該區域的新用戶,以及它們是否是可結算用戶(已輸入付款信息的用戶)。用戶可以是多個郵政編碼的客戶,並且可以在創建帳戶後隨時成爲新郵政編碼的客戶,這使我必須收集這些數據變得更加複雜。對不起,代碼混亂,我試圖添加一些評論,以顯示發生了什麼事情。搜索「// 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);
});
});
我很抱歉它是如此的長,凌亂,如果你認爲我不應該說大部分沒有得到達到該代碼的更新這一點,讓我知道。我只記得閱讀關於承諾的一些文檔,說他們在返回承諾後調用承諾的功能時會有不同的行爲。我認爲返回承諾的內部函數必須先完成,所以我會在這裏受到保護,但顯然我錯了,因爲我的提取從未被調用。
我感謝任何幫助!我一直堅持這幾個小時。
編輯 - 我已將代碼更改爲僅使用承諾,而不是混合回調和承諾。事實證明,我不需要再次獲取屬性,因爲查詢已經獲取它。我必須有一個拼寫錯誤的變量名或之前給了我一個空對象的東西。
但是,現在我的問題是用戶沒有被抓取。它基本上和以前一樣,只是在不同的地方,因爲我實際上並不需要做原始的抓取。這裏是我更新的代碼:
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);
});
});
我想我對承諾的理解有點偏離。我認爲他們幫助確保在你繼續前完成所有事情。 我一開始沒有抓取,但遇到了一些空問題。也許這是一個單獨的問題,並且取回實際上並不是必需的。我會重寫我的代碼,而不是再次獲取,看看它是否有效,如果是,請將其標爲正確。 我最初使用每個,但有一個錯誤,說你不能在一個有序數組上使用每個。按創建日期排序對統計數據非常重要,因此在這種情況下使用find是必要的。 –
我已更新我的代碼以使用承諾而不是回調。但是,我仍然遇到基本上同樣的問題,即我沒有通過獲取用戶的承諾獲得承諾。還有什麼想法?謝謝。 –
我仍然看到你的代碼中的回調,並且承諾應該被鏈接在一起。如果你承諾承諾,你需要退還,以便外部的承諾有待等待。 – Wain