Tuesday 12 February 2019

Migrating to ParseServer 3

Introduction

ParseServer 3 comes with a few breaking changes and requires a few type of changes.  I am documenting my experience of migrating my App.  Since we are all coders, I illustrate the code before and after migration in diff output format.

Approach

My current code base do not use backbone style callbacks.  I make extensive use of promises, both sequential and parallel (i.e Parse.Promise.when).  When I do migration, I keep the existing promises and therefore I do not use need to use async function.  These are the main changes:
  • Change Parse.Promise to native Promise
  • Parse.Promise.as to Promise.resolve
  • Parse.Promise.error to Promise.reject
  • Parse.Promise.when to Promise.all
  • Change cloud function
  • response.success("result") to return "result"
  • response.error("problem") to throw new Error("problem")
  • response.error(array) to throw array
  • Remove the redundant error handling block
    }, function(error) {
      response.error(error);
    });

Original

Parse.Cloud.define("getPlayer", function(request, response) {
  var player = request.params.player;

  // get session token for login user.  default to empty for non-login
  var sessionToken = {};
  if (request.user) {
    sessionToken = {sessionToken:request.user.getSessionToken()};
  }

  var p1 = exports.getPlayer(sessionToken, player);

  return p1.then(function(result) {
    response.success(result);
  },
  function(error) {
    response.error(error);
  });
});

exports.getPlayer = function(options, player)
{
  var query = new Parse.Query("Players");
  query.equalTo("name", player);
  return query.find(options);
}

Migrated

Parse.Cloud.define("getPlayer", (request) => {
  var player = request.params.player;

  // get session token for login user.  default to empty for non-login
  var sessionToken = {};
  if (request.user) {
    sessionToken = {sessionToken:request.user.getSessionToken()};
  }

  var p1 = exports.getPlayer(sessionToken, player);

  return p1.then(function(result) {
    return result;
  }); 
});

Diff output

-Parse.Cloud.define("getPlayer", function(request, response) {
+Parse.Cloud.define("getPlayer", (request) => {
   var player = request.params.player;
   // get session token for login user.  default to empty for non-login
@@ -935,37 +919,13 @@ Parse.Cloud.define("getPlayer", function(request, response) {
   var p1 = teamMod.getPlayerTeamElo(sessionToken, player);
   return p1.then(function(result) {  
-    response.success(result);
-  },
-  function(error) {
-    response.error(error);
+    return elo;
   });
 });

Cloud Function

Ordinary Cloud Function

Most of my cloud function are migrated with minor changes.  Example:

-Parse.Cloud.define("getGroup", function(request, response)
+Parse.Cloud.define("getGroup", (request) =>
 {
   if (!userMod.isLogon(request))
   {
-    response.error("Uh oh, you are not allowed to run this.");
-    return;
+    throw new Error("Uh oh, you are not allowed to run this.");
   }

   var sessionToken = userMod.getSessionToken(request);
@@ -1976,23 +1886,22 @@ Parse.Cloud.define("getGroup", function(request, response)
   var p1 = groupMod.getGroup(sessionToken,username);

   return p1.then(function(result) {
-    response.success(result);
-  }, function(error) {
-    response.error(error);
+    return groups;
   }); // p2 = p1.then

 }); // getGroup

Returning Array as Error

If you need to return array of PFObject as error.  You would need to use throw array instead of throw new Error(array).

This is the diff output.
-      response.error(matches);
+      // Note: Use throw array instead of throw new Error(array) to pass
+      //       array of PFObjects to caller.
+      //
+      // Result of throw array is
+      // error: [ ParseObject { _objCount: 6, className: 'Match', id: '12345678' },
+      //  ParseObject { _objCount: 9, className: 'Match', id: '22345678' },
+      //  ParseObject { _objCount: 11, className: 'Match', id: '32345678' },
+      //  ParseObject { _objCount: 13, className: 'Match', id: '4234567' },
+      //  ParseObject { _objCount: 15, className: 'Match', id: '52345678' } ]
+      //
+      // Result of throw new Error(array) is
+      // error: [object Object],[object Object],[object Object],[object Object],[object Object]
+      throw matches;

Triggers

Triggers are function such as beforeSave, afterSave, beforeDelete, afterDelete.  These functions are migrated in similar way as cloud functions.

-Parse.Cloud.beforeSave("Player", function(request, response) {
+Parse.Cloud.beforeSave("Player", (request) => {
   var player = request.object;

   // check if the object isNew (i.e have not been save before)
   // skip if the team record is not new
   if (!player.isNew()) {
     // no need to process and just return
-    response.success();
+    return;
   }

@@ -905,12 +892,13 @@ Parse.Cloud.beforeSave("Player", function(request, response) {

   return p1.then(function(status) {
     if (status && status.length > 0) {
-      response.success();
+      return;
     } else {
-      response.error("Player.beforeSave failed to save Player for " + game + "," + circle + ".");
+      throw new Error("Player.beforeSave failed to save Player for " + game + "," + circle + ".");
     }
   }); // p2 = p1.then

 }); // beforeSave Player

Reference


No comments:

Post a Comment