Another Parse 'success/error not called' error - javascript

I recently posted an issue I had with another Parse CloudCode method, were the error was thrown that Error: success/error was not called. I am having that issue again but with a different method/scenario.
Parse.Cloud.define("background", function(request, response) {
var moments = require("cloud/moments.js");
var now = moments.moment();
var query = new Parse.Query("Group");
query.find({
success: function(results) {
for (var i = 0; i < results.length; i++) {
var object = results[i];
var events = object.get("Events");
var getUsers = false;
for (var q = 0; q < events.length; q++) {
var e = events[q];
if (e.get("date") == now) {
getUsers = true;
break;
}
}
if (getUsers == true) {
for (var q = 0; q < events.length; q++) {
var e = events[q];
if (e.get("date") == now) {
var relation = object.relation("created");
var partOne = e.get("name");
var outString1 = partOne.concat(" is now");
// generate a query based on that relation
var query = relation.query();
Parse.Push.send({
where: query, // Set our Installation query
data: {
alert: outString1
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
// Handle error
}
});
var relation2 = object.relation("joined");
var partOnee = e.get("name");
var outString = partOnee.concat(" is now");
// generate a query based on that relation
var query2 = relation.query();
Parse.Push.send({
where: query2, // Set our Installation query
data: {
alert: outString
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
// Handle error
}
});
e.destroy();
}
}
}
}
}
});
response.success();
});
Since this method involves more than just a simple query and return (as it has the for loop among other things) I am a bit confused on how to implement the Parse Promise stuff. If anyone could assist me in how I should go about implementing the promise stuff it would be much appreciated.

Parse documentation is very clear on how to use Promises and how to rewrite your pyramid code with .then() blocks instead.

Related

Google Custom Search API for NodeJS

I'm trying to get the first 5 pages of search results with google custom search API ...
So far I've tried to achieve the result using nested function but with no luck.
I know that I'm messing with callback but, so far I've not figure out the correct way (without using promises library) to solve my problem.
Could some of you point me out in the right direction?
Thanks.
app.get('/assesment', function(req, res){
console.log('route: /assesment');
var api_key = '';
var customsearch = google.customsearch('v1');
var response = "";
var number_of_pages = 5;
var next_page = 1;
var exit = 0
const CX = 'XXXXX';
const API_KEY = 'XXXXX';
const SEARCH = 'Test Query';
console.log('start');
// console.log('QUERY PAGE: '+pages);
doSearch(CX, SEARCH, API_KEY, next_page, function(resp){
res.send(resp);
});
//
// Functions
//
function doSearch(_cx, _search, _api_key, _start, callback ){
var response = '';
customsearch.cse.list({ cx: _cx, q: _search, auth: _api_key, start: _start }, function (err, resp) {
if (err) {
response = JSON.stringify(err);
} else {
// Got the response from custom search
console.log('Result: ' + resp.searchInformation.formattedTotalResults);
if (resp.items && resp.items.length > 0) {
console.log('First result of '+resp.items.length+' is ' + resp.items[0].title);
for (var i = 0; i < resp.items.length; i++) {
response += resp.items[i].title+"<br>";
response += resp.items[i].link +"<br><hr>";
}
}
res = {
response: response,
next_page: resp.queries.nextPage
}
// res =
}
_start += 1;
if (_start < 6 ) {
doSearch(_cx, _search, _api_key, _start, _start*10+1,
function(resp){
response += resp;
});
}
if (callback && typeof callback === "function") callback(response);
});
};
});
You can use a third-party service like SerpApi to scrape Google and get back structured JSON.
Example using the Node.js library to get 4 page of results:
var gsr = require('GoogleSearchResults')
let serp = new gsr.GoogleSearchResults("demo")
serp.json({
q: "Coffee",
num: 10,
start: 30,
location: "Portland"
}, (result) => {
console.log(result)
})

Parse.com JS looping through an array when using query.find()

I'm trying to query using each elements on the array as the constraint, but so far its has only given me one result.
Here is the array:
["C44","C43","C45","C117"]
Here what I have:
{var TestObject = Parse.Object.extend("TestObject");
var query = new Parse.Query(TestObject);
query.get("W7yuUsbbav", {
success: function(testObject) {
var subjectArray = testObject.get("subjects");
for (i = 0; i < subjectArray.length ; i++ ){
console.log(subjectArray[i]);
var query = new Parse.Query("Subjects");
query.equalTo("subCode", subjectArray[i]);
query.find({
success: function(results) {
$scope.$apply(function() {
$scope.subjects1 = results.map(function(obj) {
return {subCode: obj.get("subCode"), subName: obj.get("subName"), subDesc: obj.get("subDesc")};
});
});
},
error: function(error) {
}
});
}
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});}
You can use the containedIn property of query.
var sampleId = "W7yuUsbbav";
var query1 = new Parse.Query("TestObject");
query1.get(sampleId).then(function (testObject) {
// Success
var subjectArray = testObject.get("subjects");
var query2 = new Parse.Query("Subjects");
query2.containedIn("subCode", subjectArray);
return query2.find();
}).then(function (subjectObjects) {
// Success
// results is an array of objects
}, function (error) {
// Error
});

Getting JSON from a Function in javascript

So this will be a lot of code, but what matter is on line 22-25, and line 87-91. The rest of the code works. I have a nested function and want to return the JSON string. Using console.log I can tell it is running properly but will not return the JSON string. Look for the part that says //---------this part-------. There are two parts that I am asking about.
exports.post = function(request, response) {
var mssql = request.service.mssql;
//var data = '{"userID":"ryan3030#vt.edu1"}';
var inputJSON = request.body.JSONtext;
var json = JSON.parse(inputJSON);
var userID = json.userID;
mssql.query("EXEC getMeetingInfo ?", [userID],
{
success: function(results3) {
var meetingsToday = results3.length;
var meetingID = results3[0].meetingID;
var meetingName = results3[0].meetingName;
var meetingDescription = results3[0].meetingDescription;
var meetingLength = results3[0].meetingLength;
var meetingNotes = results3[0].meetingNotes;
var hostUserID = results3[0].hostUserID;
//--------------------------------------THIS PART------------------------------
var JSONfinal = allInfoFunction(mssql, meetingID, userID, meetingName, meetingDescription, meetingLength, meetingNotes, hostUserID, meetingsToday);
console.log(JSONfinal);//DOES NOT WORk
response.send(statusCodes.OK, JSONfinal);//DOES NOT WORK
//---------------------------------BETWEEN THESE----------------------------------
},
error: function(err) {
console.log("error is: " + err);
response.send(statusCodes.OK, { message : err });
}
});
};
function allInfoFunction(mssql, meetingID, userID, meetingName, meetingDescription, meetingLength, meetingNotes, hostUserID, meetingsToday){
mssql.query("EXEC getLocation ?", [meetingID],
{ success: function(results2) {
var meetingLocation = results2[0].meetingLocation;
var JSONlocation = {"meetingLocation": meetingLocation};
mssql.query("EXEC getDateTime ?", [meetingID],
{ success: function(results1) {
var length = results1.length;
var dateTime = [];
dateTime[0] = results1[0].meetingDateTime;
for (var x= 1; x < length; x++) {
dateTime[x] = results1[x].meetingDateTime;
}
//console.log(dateTime);
mssql.query("EXEC getDateTimeVote",
{ success: function(results) {
//console.log(results);
var JSONoutput2 = {};
var JSONtemp = [];
var length2 = results.length;
for(var j = 0; j < length; j++){
var vote = false;
var counter = 0;
for(var z = 0; z < length2; z++){
var a = new Date(results[z].meetingDateTime);
var b = new Date(results1[j].meetingDateTime);
if(a.getTime() === b.getTime()){
counter = counter + 1;
}
if((a.getTime() === b.getTime()) && (results[z].userID == userID)){
vote = true;
}
}
var meetingTimeInput = {"time": b, "numVotes": counter, "vote": vote}
JSONtemp.push(meetingTimeInput);
JSONoutput2.meetingTime = JSONtemp;
}
var JSONfinal = {};
var mainInfoArray = [];
var JSONmainInfo = {meetingID: meetingID, meetingName: meetingName, meetingDescription: meetingDescription, meetingLength: meetingLength, meetingNotes: meetingNotes, hostUserID: hostUserID, meetingLocation: meetingLocation };
JSONmainInfo.meetingTime = JSONtemp;
JSONfinal.numMeetingsToday = meetingsToday;
mainInfoArray.push(JSONmainInfo);
JSONfinal.meetingList = mainInfoArray;
//response.send(statusCodes.OK, JSONfinal);
//---------------------------------------AND THIS PART-------------------------------
console.log(JSON.stringify(JSONfinal));//This outputs the correct thing
var lastOne = JSON.stringify(JSONfinal);
return lastOne; //ths dosent work
//-------------------------------------BETWEEN THESE-----------------------------------
},
error: function(err) {
console.log("error is: " + err);
//response.send(statusCodes.OK, { message : err });
}
});
},
error: function(err) {
console.log("error is: " + err);
//response.send(statusCodes.OK, { message : err });
}
});
},
error: function(err) {
console.log("error is: " + err);
//response.send(statusCodes.OK, { message : err });
}
});
}
I've done a little refactoring to your code to take a more modular approach. It becomes quite tricky to debug something like what you have above. Here it is:
exports.post = function(request, response) {
var mssql = request.service.mssql;
var inputJSON = request.body.JSONtext;
var json = JSON.parse(inputJSON);
var userID = json.userID;
var JSONFinal = {};
getMeetingInfo(userID);
function getMeetingInfo(userID){
mssql.query("EXEC getMeetingInfo ?", [userID], {
success: function(results){
JSONFinal.meetingsToday = results.length;
JSONFinal.meetingID = results[0].meetingID;
JSONFinal.meetingName = results[0].meetingName;
JSONFinal.meetingDescription = results[0].meetingDescription;
JSONFinal.meetingLength = results[0].meetingLength;
JSONFinal.meetingNotes = results[0].meetingNotes;
JSONFinal.hostUserID = results[0].hostUserID;
// Call next function
getLocation(JSONFinal);
},
error: function(err) {
console.log("error is: " + err);
response.send(statusCodes.OK, { message : err });
}
});
}
function getLocation(){
mssql.query("EXEC getLocation ?", [JSONFinal.meetingID], {
success: function(results) {
JSONFinal.meetingLocation = results[0].meetingLocation;
// Call next function
getDateTime(JSONFinal);
},
error: function(err) {
console.log("error is: " + err);
}
});
}
function getDateTime(){
mssql.query("EXEC getDateTime ?", [JSONFinal.meetingID], {
success: function(results) {
var length = results.length;
var dateTime = [];
for (var x= 0; x < length; x++) {
dateTime[x] = results[x].meetingDateTime;
}
// Call next function
getDateTimeVote(dateTime);
},
error: function(err){
console.log("error is: " + err);
}
});
}
function getDateTimeVote(dateTime){
mssql.query("EXEC getDateTimeVote", {
success: function(results) {
var JSONtemp = [];
var length2 = results.length;
for(var j = 0; j < dateTime.length; j++){
var vote = false;
var counter = 0;
for(var z = 0; z < length2; z++){
var a = new Date(results[z].meetingDateTime);
var b = new Date(results1[j].meetingDateTime);
if(a.getTime() === b.getTime()){
counter = counter + 1;
}
if((a.getTime() === b.getTime()) && (results[z].userID == userID)){
vote = true;
}
}
var meetingTimeInput = {"time": b, "numVotes": counter, "vote": vote}
JSONtemp.push(meetingTimeInput);
}
var JSONmainInfo = {
meetingID: JSONFinal.meetingID,
meetingName: JSONFinal.meetingName,
meetingDescription: JSONFinal.meetingDescription,
meetingLength: JSONFinal.meetingLength,
meetingNotes: JSONFinal.meetingNotes,
hostUserID: JSONFinal.hostUserID,
meetingLocation: JSONFinal.meetingLocation
meetingTime: JSONtemp
};
var JSONfinal = {
numMeetingsToday: JSONFinal.meetingsToday,
meetingsList: [JSONmainInfo]
};
// Call next function
sendResponse(JSON.stringify(JSONfinal));
},
error: function(err) {
console.log("error is: " + err);
}
});
}
function sendResponse(data){
response.send(statusCodes.OK, data);
}
};
It looks a lot different but the functionality is pretty much the same. The key point if you look at the code is that each subsequent function is executed only after the success of the previous function. This effectively chains the methods together so that they are always executed in order and is the key point of difference.
One thing to note here is the similarity between your
allInfoFunction(...
and my
getMeetingInfo(userID)
Both of these will return undefined more or less immediately, after the MSSQL query is sent to the server. This is because the request is fired asynchronously, and the javascript continues to run through the code. After it's fired of the asynchronous request, it has nothing left to do in that function, so it returns. There is no return value specified so it returns nothing (or undefined if you will).
So all in all, the code in the question code will return undefined and then attempt to send a response before anything has actually happened. This code fixes that problem by firing the sendResponse after all the queries have been executed.
I refactored this code in a text editor and haven't run it, or checked it for errors, so follow the basic outline all you like but it may not be a good idea to copy and paste it without checking it's not broken

Cloud code skipping section of code

I never learnt javascript so please bear with me.
I have a cloud function that does all but the indicated section (>>):
Parse.Cloud.define("acceptRequest", function(request, response) {
var user = request.user;
var requestUser;
var requestObject;
var requestId = request.params.objectId;
var query = new Parse.Query(GameRequests);
query.get(requestId,{
//Get GameRequest Object - requestObject
success: function (object) {
var requestObject = object;
var sender = requestObject.get("from");
var senderId = sender[0];
var query = new Parse.Query(Parse.User);
query.get(senderId, {
//From GameRequest Object data, find sender of request "requestUser"
success: function (userObject) {
var requestUser = userObject;
var requestUserList = requestUser.get("SENTrequests")
var requestIndex = requestUserList.indexOf(requestId);
if (requestIndex > -1) {
requestUserList.splice(requestIndex, 1);
requestUser.set("SENTrequests",requestUserList);
if (requestUserList.length = 1) {
user.unset("SENTrequests");
}
}
var userList = user.get("RCDrequests");
var userIndex = userList.indexOf(requestId);
if (userIndex > -1) {
userList.splice(userIndex, 1);
user.set("RCDrequests",userList);
if (userList.length = 1) {
user.unset("RCDrequests");
}
}
requestObject.destroy({
success: function(requestObject) {
requestUser.add("partners",user.id);
user.add("partners",requestUser.id);
var firstmsg = new GameMessage();
var secondmsg = new GameMessage();
firstmsg.set("sender", user.id);
firstmsg.set("receiver", requestUser.id);
firstmsg.set("sent", 0);
firstmsg.set("received", 0);
firstmsg.set("receiverName", requestUser.getUsername());
secondmsg.set("sender", requestUser.id);
secondmsg.set("receiver", user.id);
secondmsg.set("sent", 0);
secondmsg.set("received", 0);
secondmsg.set("receiverName", user.getUsername());
Parse.Object.saveAll([requestUser, user, firstmsg, secondmsg], { useMasterKey: true },{
>> success: function() {
>> console.log("Saving messages again");
>> firstmsg.set("otherside", secondmsg.id);
>> secondmsg.set("otherside", firstmsg.id);
>>
>> Parse.Object.saveAll([firstmsg, secondmsg]);
},
error: function(error) {
}
});
response.success("Successful");
},
error: function(requestObject, error){
}
});
},
error: function (userObject,error) {
}
});
},
error: function (object,error) {
response.error("Error");
}
});
});
It is supposed to save the two messages' objectIds so each has a reference to the other.
What is causing this problem and how can I fix it?
Thank you
I think your sending your response.success("Successful") before the save has been completed. Move your response to the success handler of the save.
You should take a look at promises section. You will not need the deep nested functions you have currently.

How can I update data in a for loop when my data is returned with a defer after the loop completes

I have two arrays:
$scope.grid.data and $scope.grid.backup
I use the following script to compare the data in each one element at a time:
for (var i = 0, len = $scope.grid.data.length; i < len; i++) {
if (!angular.equals($scope.grid.data[i], $scope.grid.backup[i])) {
var rowData = $scope.grid.data[i]
var idColumn = $scope.entityType.toLowerCase() + 'Id';
var entityId = rowData[idColumn];
entityService.putEntity($scope.entityType, entityId, $scope.grid.data[i])
.then(function (result) {
angular.copy(result, $scope.grid.data[i]);
angular.copy(result, $scope.grid.backup[i]);
}, function (result) {
alert("Error: " + result);
})
}
}
and the following to update the database:
putEntity: function (entityType, entityId, entity) {
var deferred = $q.defer();
EntityResource.putEntity({ entityType: entityType, entityId: entityId }, entity,
function (resp) {
deferred.resolve(resp);
}, function (resp) {
deferred.reject('Error updating');
});
return deferred.promise;
}
This script correctly notices the changes and updates the database.
However there is a problem when the putEntity returns with a result and it then tries to copy the result into $scope.grid.data[i] and
$scope.grid.backup[i]
This happens later and when it tries to do this it always tries to put it into element 11.
Does anyone have any ideas how I can ensure the returned data from putEntity is copied back into the correct element of the grid.data and grid.backup arrays?
You need to create a closure over i. What you can do is create a function
var updateGridData=function(entityType, entityId, gridDataToUpdate, gridIndex)
entityService.putEntity(entityType, entityId,gridDataToUpdate)
.then(function (result) {
angular.copy(result, $scope.grid.data[gridIndex]);
angular.copy(result, $scope.grid.backup[gridIndex]);
}, function (result) {
alert("Error: " + result);
})
}
So your main method becomes
for (var i = 0, len = $scope.grid.data.length; i < len; i++) {
if (!angular.equals($scope.grid.data[i], $scope.grid.backup[i])) {
var rowData = $scope.grid.data[i]
var idColumn = $scope.entityType.toLowerCase() + 'Id';
var entityId = rowData[idColumn];
updateGridData($scope.entityType, entityId, $scope.grid.data[i],i);
}
}
You can get some more idea from this question JavaScript closure inside loops – simple practical example

Categories

Resources