Search code examples
javascriptparse-servermlabheroku-apiparse-cloud-code

Parse.Cloud.beforeSave not able to set a new field on an object being created


I have a little problem in a Parse.Cloud.beforeSave function on Parse-Server. This line is puzzling me:

request.object.set("dbCount", 0);

It has been working before. But since I made a server update, to be on the heroku-18 stack, as requested by HEROKU (cedar-14 stack going end-of-life). It no longer works.

The purpose of this line is to stick a counter initialized to zero when a new item is stored in the database. But though the item is created as it should, the field "dbCount" is missing. Why is that? And what is the right code to create the field?

For reference, here is the relevant code of the beforeSave function:

Parse.Cloud.beforeSave("TheCollection", async (request) => {
 if (!request.object.isNew()) return;
 var query;
 query = new Parse.Query("TheCollection");
 query.equalTo("TITLE",request.object.get("TITLE"));

 await query.find().then
 (function(resUnit) {
  // If there is already a Unit with the same Title, we return an error.
  if (resUnit.length) throw "TITLE-USED";

  var query;
  query = new Parse.Query("TheCollection");
  var token = request.user.getSessionToken();
  query.find({sessionToken: token}).then
  (function(resUnit) {
    ... some useful processing ...
    // This next line is not working as it used to.
    request.object.set("dbCount", 0);
   });
  });
 });

Solution

  • It's possible you are missing a "return" and the save is happening before your promise resolves. I also see that you are using the same variable "resUnit" in nested scope which might be confusing it's use.

    Parse.Cloud.beforeSave("TheCollection", async (request) => {
     if (!request.object.isNew()) return;
     var query;
     query = new Parse.Query("TheCollection");
     query.equalTo("TITLE",request.object.get("TITLE"));
    
     await query.find().then
     (function(resUnit) {
      // If there is already a Unit with the same Title, we return an error.
      if (resUnit.length) throw "TITLE-USED";
    
      var query;
      query = new Parse.Query("TheCollection");
      var token = request.user.getSessionToken();
      >>>> return <<<<< query.find({sessionToken: token}).then
      (function(resUnit) {
        ... some useful processing ...
        // This next line is not working as it used to.
        request.object.set("dbCount", 0);
       });
      });
     });
    

    If you want to go a step further, I would take full advantage of async and await to flatten out your code like so. by using flat code you can eliminate a lot of the clutter that allows for bugs

    Parse.Cloud.beforeSave("TheCollection", async (request) => {
     if (!request.object.isNew()) return;
     const query = new Parse.Query("TheCollection");
     query.equalTo("TITLE",request.object.get("TITLE"));
    
     const resUnit1 = await query.first()
     // If there is already a Unit with the same Title, we return an error.
     if (resUnit) throw "TITLE-USED";
    
      const query2 = new Parse.Query("TheCollection");
      const resUnit2 = await query2.find({sessionToken: request.user.getSessionToken()})
      ... some useful processing ...
      request.object.set("dbCount", 0);
     });