Reputation: 11753
In the following Cloud function I need to know where and how to put the response.success() so that it gets executed once all the work is done and not before. I have already checked that the function is doing its job as expected. The only issue is the one I mentioned. I am trying to use Promises, but what I have done so far did not work.
Parse.Cloud.define
("deleteUnitAndDependencies", function(request, response) {
var unitListQuery;
unitListQuery = new Parse.Query("UnitList");
unitListQuery.equalTo("objectId", request.params.unitID);
unitListQuery.equalTo("ownerID", request.params.userID);
unitListQuery.find().then(function(resUnit) {
var sentenceListQuery,sentenceListStatus;
sentenceListQuery = new Parse.Query("SentenceList");
sentenceListQuery.equalTo("unit", resUnit[0]);
sentenceListStatus = sentenceListQuery.find();
resUnit[0].destroy({});
return sentenceListStatus;
}).then(function(resSentence) {
var translatListQuery,translatListQStatus;
translatListQuery = new Parse.Query("TranslatList");
for (iS = 0; iS < resSentence.length; iS++) {
if (iS == 0 ) {
translatListQuery.equalTo("sentence", resSentence[iS]);
continue;
}
translatListQuery = Parse.Query.or(translatListQuery,
(new Parse.Query("TranslatList")).equalTo
("sentence", resSentence[iS]));
}
translatListQStatus = translatListQuery.find();
for (iS = 0; iS < resSentence.length; iS++) {
resSentence[iS].destroy({});
}
return translatListQStatus;
}).then(function(resTranslat) {
for (iT = 0; iT < resTranslat.length; iT++) {
resTranslat[iT].destroy({});
}
});
});
Upvotes: 0
Views: 303
Reputation: 11753
In case someone runs into similar issues, I put here the solution I came up with. It is working the way I want, as far as I have checked at this point. If some promise-expert reads this and has comments and suggestions to make it better please let us know.
Parse.Cloud.define
("deleteUnitAndDependencies", function(request, response) {
var unitListQuery;
unitListQuery = new Parse.Query("UnitList");
unitListQuery.equalTo("objectId", request.params.unitID);
unitListQuery.equalTo("ownerID", request.params.userID);
unitListQuery.find().then
(function(resUnit) {
// If there is no UNIT we return an error.
if (!resUnit.length) response.error("NO-UNIT");
var sentenceListQuery;
sentenceListQuery = new Parse.Query("SentenceList");
sentenceListQuery.equalTo("unit", resUnit[0]);
sentenceListQuery.find().then
(function(resSentence) {
var translatListQuery,tmpQuery;
translatListQuery = new Parse.Query("TranslatList");
for (iS = 0; iS < resSentence.length; iS++) {
if (iS == 0 ) {
translatListQuery.equalTo("sentence", resSentence[iS]);
continue;
}
tmpQuery = new Parse.Query("TranslatList");
tmpQuery.equalTo("sentence", resSentence[iS]);
translatListQuery = Parse.Query.or(translatListQuery,tmpQuery);
}
translatListQuery.find().then
(function(resTranslat) {
var destroyPromises = [];
for (iT = 0; iT < resTranslat.length; iT++) {
destroyPromises.push(resTranslat[iT].destroy({}));
}
return Parse.Promise.when(destroyPromises);
}).then
(function() {
var destroyPromises = [];
for (iS = 0; iS < resSentence.length; iS++) {
destroyPromises.push(resSentence[iS].destroy({}));
}
return Parse.Promise.when(destroyPromises);
}).then
(function() {
return resUnit[0].destroy({});
}).then(response.success);
});
});
});
Upvotes: 0
Reputation: 19288
Michel, congratulations at getting it to work. That's no small achievement for someone who has been using promises for just a couple of days.
You will find that by creating a destroy()
utility, you can avoid code repetition and compact the main routine right down.
With that utility and further simplifications/rearrangements, I ended up with this :
Parse.Cloud.define("deleteUnitAndDependencies", function(request, response) {
//A utility function that gets called twice
function destroy(arr) {
return Parse.Promise.when(arr.map(function(r) {
return r.destroy({});
}));
}
var unitListQuery = new Parse.Query("UnitList");
unitListQuery.equalTo("objectId", request.params.unitID);
unitListQuery.equalTo("ownerID", request.params.userID);
unitListQuery.find().then(function(resUnit) {
var sentenceListQuery = new Parse.Query("SentenceList");
sentenceListQuery.equalTo("unit", resUnit[0]);
return sentenceListQuery.find().then(function(resSentence) {
var translatListQuery = new Parse.Query("TranslatList");
translatListQuery.equalTo("sentence", resSentence[0]);
for (var iS = 1; iS < resSentence.length; iS++) {//loop counter now starts at 1
translatListQuery = Parse.Query.or(translatListQuery, (new Parse.Query("TranslatList")).equalTo("sentence", resSentence[iS]));
}
return translatListQuery.find().then(destroy).then(function() {
return destroy(resSentence.concat(resUnit[0]));
});
});
}).then(response.success);
});
untested
Edit
As the destroys seem not to need to wait for each other, you should be able to do the .concat()
trick twice, and call destroy()
once.
return translatListQuery.find().then(function(resTranslat) {
return destroy(resTranslat.concat(resSentence).concat(resUnit[0]));
});
Upvotes: 1
Reputation: 16874
There are multiple parts in your code that return promises. You need to include these in your promise chain. This is as simple as using a return statement.
This block for example:
translatListQStatus = translatListQuery.find();
for (iS = 0; iS < resSentence.length; iS++) {
resSentence[iS].destroy({});
}
return translatListQStatus;
}).then(function(resTranslat) {
for (iT = 0; iT < resTranslat.length; iT++) {
resTranslat[iT].destroy({});
}
});
You want to wait for those destroy
calls to finish. Look at this section of the help on Promise Chaining in Parallel
var findResults;
translatListQStatus = translatListQuery.find()
.then(function(resTranslat) {
var destroyPromises = [];
for (iS = 0; iS < resSentence.length; iS++) {
destroyPromises.push(resSentence[iS].destroy({}));
}
// save these so we can return them at the end
findResults = resTranslat;
// return a promise here
return Parse.Promise.when(destroyPromises);
})
.then(function() {
// return the results we saved
return findResults;
});
return translatListQStatus;
}).then(function(resTranslat) {
var destroyPromises = [];
for (iT = 0; iT < resTranslat.length; iT++) {
destroyPromises.push(resTranslat[iT].destroy({}));
}
return Parse.Promise.when(destroyPromises);
});
Upvotes: 1
Reputation: 14563
Put a function into doSomeBigWork
, when it's done with its async stuff, have it then call that function.
doSomeBigWork(function() {
response.success();
});
Upvotes: 1