Promises on cloud code - javascript

I'm writing a cloud code function for run many task after delete an object.
How can I do this cleanly and without nesting?
You can run tasks in parallel or it is better to have them sequentially? If so, how?
This is my code, can you help me to clean/change?
Parse.Cloud.afterDelete("Photo", function(request) {
Parse.Cloud.useMasterKey();
//delete all related activities
var queryAct = new Parse.Query("Activity");
queryAct.equalTo("photo",{
__type: "Pointer",
className: "Photo",
objectId: request.object.id
});
queryAct.limit(1000);
queryAct.find({
success: function(activities) {
Parse.Object.destroyAll(activities, {
success: function() {
//delete all related hashtags
var queryTags = new Parse.Query("hashTags");
queryTags.equalTo("photo",{
__type: "Pointer",
className: "Photo",
objectId: request.object.id
});
queryTags.limit(1000);
queryTags.find({
success: function(hashtags) {
Parse.Object.destroyAll(hashtags, {
success: function() {},
error: function(error) {
console.error("Error deleting related hashtags " + error.code + ": " + error.message);
}
});
},
error: function(error){
console.error("Error finding related hashtags " + error.code + ": " + error.message);
}
});
},
error: function(error) {
console.error("Error deleting related activities " + error.code + ": " + error.message);
}
});
},
error: function(error) {
console.error("Error finding related activities " + error.code + ": " + error.message);
}
});
});
Thanks to all!

Here find.then.delete is a series of tasks in a row. However, you can delete your hastags and activities in parallel since they don't seem to be dependent. Please check promises guide for more info.
Your code can be shortened as below:
var Photo = Parse.Object.extend("Photo");
Parse.Cloud.afterDelete("Photo", function(request) {
Parse.Cloud.useMasterKey();
var photo = Photo.createWithoutData(request.object.id);
var queryAct = new Parse.Query("Activity");
queryAct.equalTo("photo", photo);
queryAct.limit(1000);
var promiseForActivities = queryAct.find().then(function (activities) {
return Parse.Object.destroyAll(activities);
});
var queryTags = new Parse.Query("hashTags");
queryTags.equalTo("photo", photo);
queryTags.limit(1000);
var promiseForHashtags = queryTags.find().then(function (hashtags) {
return Parse.Object.destroyAll(hashtags);
});
return Parse.Promise.when([promiseForActivities, promiseForHashtags]).then(function () {
console.log("Done");
}, function (err) {
console.error(err);
});
});
Note that you don't need to create your own pointer objects like:
{
__type: "Pointer",
className: "Photo",
objectId: "someId"
}
Rather you can use createWithoutData which is a shortcut for:
var Photo = Parse.Object.extend("Photo");
var p = new Photo();
p.id = "someId";
I also think that it could be enough to pass the request.object directly, like queryAct.equalTo("photo", request.object);

Related

Google Cloud Function frozen for over minute

have a strange thing happening running a Google cloud function. The function starts and logs the user id and job id as expected. Then it calls firestore db and basically sits there for 1 minute, sometimes 2 before it executes the first call... It was even timing out on 240 seconds.
const AWS = require('aws-sdk');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.run = functions.https.onCall((data, context) => {
var id = data.id;
var userid = data.uid;
var retry = data.retry;
var project;
var db = admin.firestore();
var storage = admin.storage();
console.log("Starting Collect");
console.log("UID: " + userid);
console.log("id ID: " + id);
// Times out on this call
db.collection("users").doc(userid).collection("ids").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
createexport();
}).catch(function(err) {
console.log(err);
error('Loading DB Error, ' + err, false);
});
function createexport() {
db.collection("exports").doc(id).set({
status: 'Collecting',
stage: 'Export Checker',
percent: 0,
id: id,
}).then(function() {
console.log("Creating Export");
setdb();
}).catch(function(err) {
error("Error creating export in database :" + err, true)
});
}
function setdb() {
db.collection("users").doc(userid).collection("ids").doc(id).update({
status: 'Analyzing Files',
stage: 'Collecting'
}).then(function() {
getaudio();
}).catch(function(err) {
error("Error updating users id in database :" + err, true)
});
}
function getaudio() {
const from = userid + '/projects/' + project.originalproject.id + '/audio.' + project.originalproject.extension;
const to = userid + '/' + id + '/audio.' + project.originalproject.extension;
storage.bucket('---------').file(from).copy(storage.bucket('---------').file(to)).then(function() {
console.log("Collecting files");
copy2();
}).catch(function(err) {
error('Collecting Audio Error, ' + err, true);
});
}
function copy2() {
const from = userid + '/projects/' + project.originalproject.id + '/overlay.png';
const to = userid + '/' + id + '/overlay.png';
storage.bucket('--------.appspot.com').file(from).copy(storage.bucket('---------').file(to)).then(function() {
updateexport();
}).catch(function(err) {
error('Collecting Overlay Error, ' + err, true);
});
}
function updateexport() {
db.collection("exports").doc(id).update({ status: "Waiting" }).then(function() {
console.log("All files collected");
return { status: 'Success' };
}).catch(function(err) {
error("Error creating export entry in database :" + err, true)
});
}
function error(evt, evt2) {
AWS.config.update({ region: "us-east-1" });
var html;
var sub = 'Error with id ' + id;
console.log(evt);
if (evt2) {
db.collection('users').doc(userid).collection('ids').doc(id).update({
status: 'Error'
}).catch(function(err) {
console.log(err);
});
db.collection("exports").doc(id).update({
status: 'Error',
stage: 'Collecting',
error: evt,
}).catch(function(err) {
console.log(err);
});
html = `
Username: ${project.username} <br>
UserID: ${userid} <br>
Email: ${project.email} <br>
id: ${id}
`
} else {
html = `id: ${id}<br>
UserID: ${userid} <br>
Message: Error logged was: ${evt}
`
}
var params = {
Destination: {
ToAddresses: [
'errors#mail.com'
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: html
},
},
Subject: {
Charset: 'UTF-8',
Data: sub
}
},
Source: 'errors#mail.com',
ReplyToAddresses: [
project.email
],
};
var sendPromise = new AWS.SES({
apiVersion: "2010-12-01",
"accessKeyId": "-----------",
"secretAccessKey": "------------------------",
"region": "--------",
}).sendEmail(params).promise();
sendPromise.then(function(data) {
return { data: data };
}).catch(function(err) {
return { err: err };
});
}
});
Seems to me to be way too long for a database call of only a few kb. I will attach the cloud log to show time difference. After this initial slump it then performs as expected.
Cloud log image
Anyone got any ideas as to why this could be happening? Many thanks...
Your function is appearing to hang because it isn't handling promises correctly. Also, it doesn't appear to be sending a specific response to the client app. The main point of callable functions is to send a response.
I suggest reviewing the documentation, where you will learn that callable functions are required to return a promise that resolves with an object to send to the client app, after all the async work is complete.
Minimally, it will take a form like this:
return db.collection("users").doc(userid).collection("files").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
return { "data": "to send to the client" };
}
Note that the promise chain is being returned, and the promise itself resolves to an object to send to the client.

Uncaught SyntaxError: Unexpected string in my javascript file

This is my likedc.js which I tried to upload but however the terminal reported me that it is failed because Error: Uncaught SyntaxError: Unexpected string in likedc.js:40 at main.js:3:1
I tried to comment but the terminal still says the same thing. I'm not sure what are the alternatives that I can amend
Parse.Cloud.define("StatusUpdate", function(request,response){
//query Installation for user
var Installationquery = Parse.Object.extend("Installation");
var query = new Parse.Query(Installationquery);
var message = request.params.message
query.equalTo("user", request.params.User);
query.find({
success: function(results) {
response.success("found user" + results)
// Do something with the returned Parse.Object values
for (var i = 0; i < results.length; i++) {
var object = results[i];
Parse.Push.send({
where: query, // Set our Installation query
data: {
alert: createMessage(message)
badge: "Increment", **//<---- Line 40**
sound: "";
}
}, {
success: function() {
// Push was successful
console.log("sent ")
},
error: function(error) {
console.log("Error " + error)
}
}
},
error: function(error) { // <--- Line 54**
alert("Error: " + error.code + " " + error.message);
}
});
})
});
var alertMessage = function createMessage(request)
{
var message = "";
if (request.object.get("StatusUpdate") === "likedby") {
if (request.user.get('postedby')) {
message = request.user.get('postedby') + ': ' + request.object.get('statusOBJID').trim();
} else {
message = "Someone liked on your status update.";
}
// Trim our message to 140 characters.
if (message.length > 140) {
message = message.substring(0, 140);
}
return message;
}
}
data: {
alert: createMessage(message), //<-- add comma here
badge: "Increment", **//<---- Line 40**
sound: "" //<-- remove semicolon here
}
For the second part, from the context I think your error block is out of place, try rearranging like
Parse.Cloud.define("StatusUpdate", function(request, response) {
//query Installation for user
var Installationquery = Parse.Object.extend("Installation");
var query = new Parse.Query(Installationquery);
var message = request.params.message
query.equalTo("user", request.params.User);
query.find({
success: function(results) {
response.success("found user" + results)
// Do something with the returned Parse.Object values
for (var i = 0; i < results.length; i++) {
var object = results[i];
Parse.Push.send({
where: query, // Set our Installation query
data: {
alert: createMessage(message),
badge: "Increment", //<---- Line 40**
sound: ""
}
}, {
success: function() {
// Push was successful
console.log("sent ")
},
error: function(error) {
console.log("Error " + error)
}
});
}
},
error: function(error) { // <--- Line 54**
alert("Error: " + error.code + " " + error.message);
}
});
});

Trying to add player object to an array of players within my session

I'm trying to create a Lobby for a web game I'm working on and I want to add the person who is creating the lobby to the lobby's "Players" array. I'm using parse and I can't for the life of me figure out how to append just the player object into the array. Any help is great!
function createLobby(){
var ses = Parse.Object.extend("Session");
var query = new Parse.Query(ses);
var exists = false;
query.equalTo("sessionName", document.getElementById("lobby").value);
query.find({
success: function(results) {
console.log("Successfully retrieved " + results.length );
if(results.length!=0){
alert("Session already exists");
exists = true;
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
if(exists==false){
session.set("sessionName",document.getElementById("lobby").value);
var Players = Parse.Object.extend("Player");
var query = new Parse.Query(Players);
query.equalTo("Name", "testName");
query.find({
success: function(results) {
var query2 = new Parse.Query(Players);
query2.get(results[0].id, {
success: function(k) {
console.log(k);
session.add("Players", k);
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
session.save(null, {
success: function(object) {
$(".success").show();
},
error: function(model, error) {
$(".error").show();
}
});
}
}
You're failing to understand how callbacks work. I recommend you read about JavaScript callbacks and promises. Here's how this should be written:
function createLobby() {
var ses = Parse.Object.extend("Session");
var query = new Parse.Query(ses);
var exists = false;
query.equalTo("sessionName", document.getElementById("lobby").value);
query.find({
success: function(results) {
console.log("Successfully retrieved " + results.length);
if (results.length != 0) {
alert("Session already exists");
return;
}
session.set("sessionName", document.getElementById("lobby").value);
var Players = Parse.Object.extend("Player");
var query = new Parse.Query(Players);
query.equalTo("Name", "testName");
query.find({
success: function(results) {
var query2 = new Parse.Query(Players);
query2.get(results[0].id, {
success: function(k) {
console.log(k);
session.add("Players", k);
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
session.save(null, {
success: function(object) {
$(".success").show();
},
error: function(model, error) {
$(".error").show();
}
});
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}

Find objects with field value (this is a pointer)

I have class say 'inspection' and there is a field name property (this is a pointer) . I am trying to retrieve a record by field value but getting nothing as a result. I am using following code
getInspectionByProperty = function(req) {
console.log(req.body.propertyId)
var query = new Parse.Query("Inspection");
query.include('property');
query.equalTo('property', req.body.propertyId);
query.find({
success: function(data) {
console.log('in success');
console.log(data);
// Successfully retrieved the object.
},
error: function(error) {
console.log('in error')
console.log("Error: " + error.code + " " + error.message);
}
});
};
I am getting this error in parse log
Error: 102 pointer field property needs a pointer value
How can i get the record .Thanks in advance
Here what i try and thats work for me.
getInspectionByProperty = function(req) {
console.log(req.body.propertyId)
var query = new Parse.Query("Inspection");
query.include('property');
query.equalTo("property", {
"__type": "Pointer",
"className": "Property",
"objectId": propertyId
});
query.find({
success: function(data) {
console.log('in success');
console.log(data);
// Successfully retrieved the object.
},
error: function(error) {
console.log('in error')
console.log("Error: " + error.code + " " + error.message);
}
});
};

Parse custom class (JavaScript)

In a nutshell, I have created register and login functionalities. The problem is that I do not want the information/retrieved from the default User class, but from a custom one, such as Customers, however, i do not know how to change it.
This is how I refer to the default class (User).
$scope.signUp = function(form) {
var user = new Parse.User();
user.set("password", form.password);
user.set("username", form.username);
user.signUp(null, {
success: function(user) {
window.location = 'myprofile.php'
},
error: function(user, error) {
alert("Unable to sign up: " + error.code + " " + error.message);
}
});
};
$scope.logIn = function(form) {
Parse.User.logIn(form.lusername, form.lpassword, {
success: function(user) {
window.location = 'admin.php'
},
error: function(user, error) {
alert("Unable to log in: " + error.code + " " + error.message);
}
});
};
$scope.logOut = function(form) {
Parse.User.logOut();
window.location = 'index.html'
};
}]);

Categories

Resources