0

What's up, SO?

I have a cloud code function that runs some queries to ensure that what I want to do is allowed at the current time. If those queries tell me that it is not allowed, I call response.error() with an explanation of why, and I have an else statement that returns another promise to run a new query or do something else.

I've found that even though I called response.error() and didn't return a promise, it's jumping to the next link in the chain, which is resulting in some undefined behavior, and very problematically modifying things that I don't want modified.

Is my only option to set a flag and check it at every step of the way down my chain? I feel like there has to be a better way to exit out of the chain prematurely.

Thanks for any tips / feedback, I really appreciate it.

Edit - Here's an example of where this issue is occurring. I'm using Stripe as my payment platform, and want users to be able to delete their cards. Since I use Stripe Connect Market with managed accounts, I have to create / capture charges based on provider actions rather than user request times, so I store the card token they chose instead. I need to make sure that that card is not deleted from their account if I still need it to charge the customer. Currently, I don't allow users to delete cards at all if they have any active/scheduled services, but I've had users complain about that already, so I want to implement the delete feature better.

Parse.Cloud.define("StripeDeleteCard", function(request, response)
{
    //Parse objects
    var query1 = new Parse.Query("Class1");
    var query2 = new Parse.Query("Class2");
    //passed in parameters
    var customer_id = request.params.customer_id;
    var card_id = request.params.card_id;

    //Set up queries to ensure the card is not being used on an instance of Class1 or Class2
    query1.equalTo("customerCard", card_id);
    query2.equalTo("customerCard", card_id);

    query1.count().then
    (
        function( number )
        {
            if( number > 0 )
            {
                response.error("CARD CAN NOT BE DELETED BECAUSE IT IS BEING USED AS THE PAYMENT METHOD FOR AN ACTIVE SERVICE REQUEST!"); //This is where I want my function to end
            }
            else
            {
                return query2.count(); //This isn't actually getting called, so "number" is nil in the next link
            }
        },
        function( error )
        {
            response.error("Failed to query for Class1 using this card_id: " + error.message);
        }
    ).then //Everything after this shouldn't execute
    (
        function( number ) //number is not set since no promise was returned
        {
            if( number > 0 )
            {
                response.error("CARD CAN NOT BE DELETED BECAUSE IT IS BEING USED AS THE PAYMENT METHOD FOR A SCHEDULED SERVICE REQUEST!");
            }
            else //This block gets called anyway, since number == 0
            {
                return Parse.Cloud.httpRequest(
                            {
                                method:"DELETE",
                                url: "https://" + STRIPE_SECRET_KEY + ':@' + STRIPE_API_BASE_URL + "/customers/" + customer_id + "/cards/" + card_id
                            }
                        );
            }
        },
        function( error )
        {
            response.error("Failed to query for Class2 using this card_id: " + error.message);
        }
    ).then
    (
        function( httpResponse )
        {
            response.success("Card Deleted."); //I just deleted a card that should not have been deleted
        },
        function( error )
        {
            response.error("Failed to delet the card: " + error.message);
        }
    );
});
Jake T.
  • 4,308
  • 2
  • 20
  • 48
  • have you tried throwing? – Daniel A. White Sep 18 '15 at 19:10
  • Nope. But that sounds very viable. I'll post an update after I try it, though I've never implemented catch/throw blocks with javascript, so we'll see how that goes! haha – Jake T. Sep 18 '15 at 19:21
  • Hard to tell without a code sample, but it sounds like you're not using promises correctly -- you should always return the promise, then call the promise's `.success()` or `.error()` asynchronously as needed; `.error()` will stop the chain. – Daniel Beck Sep 18 '15 at 19:24
  • The promises I'm returning are all built in Parse methods, like querying, saving, destroying, etc. I have very few of my own custom promises, and those are all working fine, from what I can tell. I'll update my question with an example of a use case, if you don't mind checking and letting me know if you still think I'm using promises incorrectly. – Jake T. Sep 18 '15 at 19:31
  • @DanielBeck I've added an example. – Jake T. Sep 18 '15 at 19:41
  • @DanielA.White , I'm looking at implementing the try / catch blocks, but I'm not 100% sure how the best way to implement them is. I looked at the example in the link below, but I don't want to get rid of my more descriptive errors telling me what was going on when I threw an error, so I'm not sure a generic promise.reject at the end will be sufficient. I'm thinking I should keep my code more or less the way it is, but put the chain (or even everything in the function) in a try block, throw anything after I call response.success/reject, and not actually do anything in the catch block. – Jake T. Sep 18 '15 at 19:58

0 Answers0