I've got a cloud code function which marks Notification objects as "read" and then queries the same class immediately for remaining "unread" objects.
The problem is the most times, the same Notification objects I mark as read are returned in my preceding unread query, even if the values have been updated in data browser.
When I changed from Parse.Promise.when()
to Parse.Object.saveAll()
, that solved the issue, but it's still unclear why. The when promise is supposed to be resolved when all the save()
operations complete and hence will not run the last "unread" query until they've been marked as read.
What does Parse.Object.saveAll(objects)
do that Parse.Promise.when(promiseListOfSaves)
doesn't?
Code examples of each below. Not much difference between the two aside from the way objects are being saved.
Parse.Cloud.define('markThreadReadAndReturnUnreadCount', function(request, response){
var promiseChain = [];
var Notification = Parse.Object.extend("Notification");
qry = new Parse.Query(Notification);
qry.equalTo('owner', request.user);
qry.equalTo('read', false);
qry.equalTo('messageThreadId', request.params.threadId);
qry.find(null, {useMasterKey: true}).then(function(_notifications){
_.each(_notifications, function(_notification){
notification = new Notification();
notification.id = _notification.id;
notification.set('read', true);
promiseChain.push(notification.save(null, {wait: true}));
});
return Parse.Promise.when(promiseChain);
}).then(function(){
var countUnreadQuery = new Parse.Query(Notification);
countUnreadQuery.equalTo('owner', user);
countUnreadQuery.equalTo('read', false);
countUnreadQuery.find({useMasterKey: true}).then(function(results){
return response.success(results.length);
}
};
});
with Parse.Object.saveAll();
Parse.Cloud.define('markThreadReadAndReturnUnreadCount', function(request, response){
var saveObjects = [];
var Notification = Parse.Object.extend("Notification");
qry = new Parse.Query(Notification);
qry.equalTo('owner', request.user);
qry.equalTo('read', false);
qry.equalTo('messageThreadId', request.params.threadId);
qry.find(null, {useMasterKey: true}).then(function(_notifications){
_.each(_notifications, function(_notification){
notification = new Notification();
notification.id = _notification.id;
notification.set('read', true);
saveObjects.push(notification);
});
return Parse.Object.saveAll(saveObjects);
}).then(function(){
var countUnreadQuery = new Parse.Query(Notification);
countUnreadQuery.equalTo('owner', user);
countUnreadQuery.equalTo('read', false);
countUnreadQuery.find({useMasterKey: true}).then(function(results){
return response.success(results.length);
}
};
});
I am not sure why saveAll
works where when
doesn't work, but I would prefer saveAll
over when
in this scenario for two reasons:
The code style, what looks better of the two options below:
function save(objects){
return Parse.Promise.when(objects.map(function(object){
return object.save(null, {wait: true});
}));
}
// or
function save(objects){
return Parse.Object.saveAll(objects);
}
Performance, when you use an array of save, you send n
http requests for the n
objects you want to save, this is a huge waste of resources, but when you use saveAll
you send only one request for all of them.
also I think your second code can be reduced to:
...
qry.find(null, {useMasterKey: true}).then(function(_notifications){
_.each(_notifications, function(_notification){
notification.set('read', true);
});
return Parse.Object.saveAll(_notifications);
}).then(function(){
...