Phineas
Phineas

Reputation: 319

beforeSave doesn't modify request.object

I'm trying to add some additional attributes for new user through cloud code:

Parse.Cloud.beforeSave(Parse.User, (request) => {
    if (!request.original) {
        // New user
        Parse.Config.get()
            .then((config) => {
                const ProfileIcon = Parse.Object.extend("ProfileIcon");
                const iconId = config.get("defaultProfileIcon");
                const user = request.object;
                // ...many user.set
                user.set("profileIcon", ProfileIcon.createWithoutData(iconId), {
                    useMasterKey: true,
                }); // Pointer
                // This will save as expected, but cause recursion
                // user.save({ useMasterKey: true });
            })
            .catch((err) => {
                console.error(err);
            });
    }
});

The code above triggered and executed without any error, but when I check the database, none of my custom attributes show up. Passing the master key also does nothing. How can I fix this?
Or is it because the request from the client (Android, have no access to master key), if so then how can I set master key for the request, since Parse.Cloud.useMasterKey() is deprecated?

Upvotes: 1

Views: 350

Answers (2)

Austin Murdock
Austin Murdock

Reputation: 21

Your problem is not a missing return, it's a synchronicity problem. When dealing with promises the thread is unblocked once the promise is created allowing the remained of your function (including code being returned) to resolve before jumping back to completion of the promise upon resolution of the wait trigger (DB request here).

For example you could do the following and it would work fine:

Parse.Cloud.beforeSave(Parse.User, ({ object }) => {
 object.set('username', 'foo');
});

As this is modifying the object that's being passed along (interceptor on the save command from elsewhere). However in your case you're performing a promise request which is async so something like:

Parse.Cloud.beforeSave(Parse.User, async ({ object }) => {
  const config = await Parse.Config.get();
  user.set('username', config.get('defaultUsername'));
});

Would be more of a parallel, when using async/await a promise is always returned into the resolution so the promise based equivalent of the above would be:

Parse.Cloud.beforeSave(Parse.User, ({ object }) => {
  return Parse.Config.get().then((config) => {
    user.set('username', config.get('defaultUsername'));
  });
});

The beforeSave hook will wait for promises that are returned (when needed), you can also return values inside of your Promise.then to get success messages or throw to get error messages.

Upvotes: 0

Phineas
Phineas

Reputation: 319

Here, modifying object on save does not mention anything about return, but before save file does. So I thought I would give it a try, turns out it worked. Still not sure if this is the right way though.

Upvotes: 1

Related Questions