2

I am new to JavaScript and I am trying to get my first bits of CloudCode working. I have created a helper function deleteFriendRequest as I will want this to be used by other functions. What I have written works but I get an error thrown.

My helper function:

function deleteFriendRequest(requestObjectId) {
    // create query to find FriendRequest from its objectId
    var requestQuery = new Parse.Query("FriendRequest");
    requestQuery.equalTo("objectId", requestObjectId);
    return requestQuery.first().then(function(friendRequestObj) {
        return friendRequestObj.destroy();
    });

}

A function where it is used:

Parse.Cloud.define("createFriendship", function(request, response) {
    Parse.Cloud.useMasterKey();

    var currentUser = request.user;
    var friendRequestId = request.params.friendRequestObjectId;

    var fromUser;
    var fromRelation;

    var requestQuery = new Parse.Query("FriendRequest");
    requestQuery.equalTo("objectId", friendRequestId);
    requestQuery.include("fromUser");
    requestQuery.first().then(function(friendRequestObj) {
            fromUser = friendRequestObj.get("fromUser");
            fromRelation = currentUser.relation("friendsRelation");
            fromRelation.add(fromUser);
            return currentUser.save();
        }).then(function(friendRequestObj) {
            var toRelation = fromUser.relation("friendsRelation");
            toRelation.add(currentUser);
            return fromUser.save();
        }).then(deleteFriendRequest(friendRequestId))
        .then(function(error) {
            response.error(error);
        });

});

When I run createFriendship I get the following error:

Input: {"friendRequestObjectId":"qVIa9zzPR0"}
Result: TypeError: Object [object Object] has no method 'apply'
    at e (Parse.js:2:8941)
    at Parse.js:2:8390
    at Array.forEach (native)
    at Object.x.each.x.forEach [as _arrayEach] (Parse.js:1:661)
    at c.extend.resolve (Parse.js:2:8341)
    at Parse.js:2:9020
    at e (Parse.js:2:8941)
    at Parse.js:2:8390
    at Array.forEach (native)
    at Object.x.each.x.forEach [as _arrayEach] (Parse.js:1:661)

Thanks in advance for any help anyone can offer.

  • What you have given will not help solve the problem as the error is deep in the Parse.js source. `apply()` is a method of the Function object. You may be passing an object where you should be passing a function. – Blindman67 Aug 18 '15 at 14:34

2 Answers2

1

The expression ...

`.then(deleteFriendRequest(friendRequestId))` 

... calls deleteFriendRequest(friendRequestId) immediately and passes the returned promise to .then().

However, .then() accepts functions as its arguments, not promises.

Try :

.then(function() {
    deleteFriendRequest(friendRequestId);
})

or

.then(deleteFriendRequest.bind(null, friendRequestId))

Going further ...

Much of what is in deleteFriendRequest() is the derivation of friendRequestObj, which is a repetition of work already done in the caller function, so unless deleteFriendRequest() is needed elsewhere in the app, the line return friendRequestObj.destroy(); can be moved to the caller, and deleteFriendRequest() can disappear.

Parse.Cloud.define("createFriendship", function(request, response) {
    Parse.Cloud.useMasterKey();
    var requestQuery = new Parse.Query("FriendRequest");
    requestQuery.equalTo("objectId", request.params.friendRequestObjectId);
    requestQuery.include("fromUser");
    requestQuery.first()
    .then(function(friendRequestObj) {
        var fromUser = friendRequestObj.get("fromUser");
        request.user.relation("friendsRelation").add(fromUser);
        fromUser.relation("friendsRelation").add(request.user);

        // The two saves can most likely be performed in parallel
        return Parse.Promise.when(
            request.user.save(), 
            fromUser.save()
        )
        .then(function() {
            return friendRequestObj.destroy(); //<<<<<<<< moved here from deleteFriendRequest()
        });
    })
    .then(response.success, response.error);
});
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • Thanks, this has really helped in a good few ways with my understanding. Your last "Going further..." suggestion would seem to fit the job best but I still get `success/error was not called` when things work so I'm missing a `response.success`. Where would be most appropriate in here to put this? – John Hughes Aug 18 '15 at 20:01
  • Good point, `response.success` is not called. In the penultimate line, a `null` shifts `response.error` into second place of .then()'s parameter list. The `null` should really be replaced with a function. At its simplest, that could be `response.success`. To actually serve a success message you will need something like `.then(function() { response.success("my success message"); }, response.error);` Let me know if that works and I'll edit my answer. – Roamer-1888 Aug 18 '15 at 20:25
  • 1
    Replacing the `null` with `response.success` serves my needs. Thank you very much for your help!! – John Hughes Aug 18 '15 at 20:35
0

Try using Parse.Cloud.useMasterKey(); in the deleteFriendRequest method. Looks like the current user may not have access to that row.

Your other option may be to try setting the ACL when the friend request is created. Youll have to use the master key again, but you can set the ACL at that stage to include the current user and the requested friend. That way they both have access to it.

RonnyKnoxville
  • 6,166
  • 10
  • 46
  • 75
  • `createFriendship` works in that it creates the required relation and it deletes the friend request, but I get that error so my Android client gets an exception and thinks the function failed. It doesn't seem like its to do with access since it does what it's supposed to in that respect. Thoughts? – John Hughes Aug 18 '15 at 14:15