As the title states, I'm having trouble with Promises in Parse.
I'm struggling to firstly understand exactly how Promises themselves work, especially in Parse.
I have been stuck on this for about three weeks and the closest I've come to a solution is having an empty array returned.
What I'm trying to do is scrape a site and then create objects from the table (this is working)
Where there trouble comes in, is I am then running a for loop on the results and querying each Dam name to get the resulting objectid from the database.
Here is my code:
var c = new Crawler({
maxConnections: 10,
// This will be called for each crawled page
callback: function(err, res, done) {
if (err) {
console.log(err);
} else {
var $ = res.$;
// $ is Cheerio by default
//a lean implementation of core jQuery designed specifically for the server
console.log($("title").text());
}
done();
}
});
The Function which Creates objects from the Dom and adds them to an array:
function getDamObjects(Dom) {
var dom = Dom;
var LevelObjects = [];
for (i = 1; i < dom.length - 1; i++) {
var TableRow = dom.eq(i);
var NameString = TableRow.children().eq(0).text();
var RiverString = TableRow.children().eq(1).text();
var FSCString = TableRow.children().eq(4).text();
var ThisWeekString = TableRow.children().eq(5).text();
var LastWeekString = TableRow.children().eq(6).text();
var LastYearString = TableRow.children().eq(7).text();
NameString = NameString.replace('#', '');
NameString = NameString.replace('$', '');
NameString = NameString.replace('&', '');
NameString = NameString.replace('@', '');
ThisWeekString = ThisWeekString.replace('#', '');
ThisWeekString = ThisWeekString.replace('$', '');
ThisWeekString = ThisWeekString.replace('&', '');
ThisWeekString = ThisWeekString.replace('@', '');
LastWeekString = LastWeekString.replace('#', '');
LastWeekString = LastWeekString.replace('$', '');
LastWeekString = LastWeekString.replace('&', '');
LastWeekString = LastWeekString.replace('@', '');
LastYearString = LastYearString.replace('#', '');
LastYearString = LastYearString.replace('$', '');
LastYearString = LastYearString.replace('&', '');
LastYearString = LastYearString.replace('@', '');
var level = {};
/*
getDamObject(NameString).then(function(DamObject){
let DamID = DamObject.id;
*/
level['Dam'] = NameString; //DamID;
level['ThisWeek'] = ThisWeekString;
level['LastWeek'] = LastWeekString;
level['LastYear'] = LastYearString;
LevelObjects.push(level);
};
return LevelObjects;
};
The Get Dam Object Code:
function getDamObject(Dam) {
var promise = new Parse.Promise();
var query = new Parse.Query("DayZeroDams");
query.equalTo("Name", Dam);
query.first().then(function(DamObject) {
promise.resolve(DamObject);
}, function(error) {
promise.reject(error);
});
return promise;
}
The Cloud Code Called:
Parse.Cloud.define('jsdom', function(request, response) {
c.queue([{
uri: 'xxxxxx',
// The global callback won't be called
callback: function(err, res, done) {
if (err) {
response.error(err);
} else {
var $ = res.$;
var ResultsArray = [];
var dom = res.$('#mainContent_tw').children('tr');
return Parse.Promise.as().then(function() {
var promise = Parse.Promise.as();
var LevelObjects = getDamObjects(dom);
_.each(LevelObjects, function(DamLevel) {
promise = promise.then(function() {
var Name = DamLevel["Dam"];
var query = new Parse.Query("DayZeroDams");
query.equalTo("Name", Name);
return query.first().then(function(result) {
let damID = result.id;
ResultsArray.push(damID);
return Parse.Promise.as();
}, function(error) {
response.error(error);
});
});
});
return promise;
}).then(function() {
response.success(ResultsArray);
}, function(error) {
response.error(error);
});
//response.success(LevelObjects);
}
done();
}
}]);
});
Please take note that I am fairly novice when it comes to Javascript, I have only recently started learning it in order to work with my server code.
Convert getDamObjects
into an async function and then await
the result of each row, pushing it to the array:
function replaceSymbols(input) {
return input.replace(/[#\$&@]/g, '');
}
async function getDamObjects(Dom) {
const dom = Dom;
const levelObjects = [];
for (let i = 1; i < dom.length - 1; i++) {
const children = dom.eq(i).children();
const NameString = replaceSymbols(children.eq(0).text());
const RiverString = children.eq(1).text();
const FSCString = children.eq(4).text();
const ThisWeek = replaceSymbols(children.eq(5).text());
const LastWeek = replaceSymbols(children.eq(6).text());
const LastYear = replaceSymbols(children.eq(7).text());
const Dam = await getDamObject(NameString);
levelObjects.push({
Dam,
ThisWeek,
LastWeek,
LastYear,
});
}
return levelObjects;
}
Remember that now that getDamObjects is an async function, it will return a Promise that resolves to the array once iterations are complete. Consume it using await getDamObjects
in another async function (or use .then
)