Javascript/ - Promises, Calling Response.success() Inside Promise

- 1 answer

I have a promise chain that performs a query, checks the results, and if I find what I need it calls response.success(), and if not, it moves to the next query... for some reason though when I call response.success() the next promise gets executed. Doesn't response.success() end the function?

This code essentially checks each one of my roles to see which one the requesting user belongs too.

How do I stop the promise chain when I call response.success()?

Parse.Cloud.define('getUserRole', function (request, response) {


    const NAME = "name";
    const USER = "user";
    const USERNAME = "username";
    const CUSTOMER_ROLE = "Customer";
    const BARBER_ROLE = "Barber";
    const ADMIN_ROLE = "Admin";

    var user = request[USER];
    if (user == null){
        console.log("@Null Check for user");
    } else {
        console.log("Username: " + user.get(USERNAME));

    //Query customers first because that is the most likely role for most cases
    var customerRoleQuery = new Parse.Query(Parse.Role);
    customerRoleQuery.equalTo(NAME, CUSTOMER_ROLE);
    customerRoleQuery.first().then(function (role) {
        console.log("@query customer Role: " + JSON.stringify(role));

        //Customer Role

        var customerQuery = role.getUsers().query();
        customerQuery.equalTo(USERNAME, user.get(USERNAME));
        return customerQuery.first();

    }).then(function (user) {
        console.log("@query for customer users: " + JSON.stringify(user));

        //Check if we found the user in the customer role

        if (user){
            console.log("@ customer user");
            //We found the user in the customer role
        } else {
            console.log("@ barber role query");
            //We didn't find the user in the customer role, get the barber role.
            var barberRoleQuery = new Parse.Query(Parse.Role);
            barberRoleQuery.equalTo(NAME, BARBER_ROLE);
            return barberRoleQuery.first();

    }).then(function (role) {
        console.log("@query Barber Role: " + JSON.stringify(role));

        //Barber Role

        var barberQuery = role.getUsers().query();
        barberQuery.equalTo(USERNAME, user.get(USERNAME));
        return barberQuery.first();

    }).then(function (user) {
        console.log("@query for barber users: " + JSON.stringify(user));

        //Check if we found the user in the barber role

        if (user){
            //We found the user in the barber role
        } else {
            //We didn't find the user in the barber role, get the admin role
            //This may seem unnecessary, but we can't assume if we didn't find them in the customer or barber roles they are admins. That is a security risk.
            var adminRoleQuery = new Parse.Query(Parse.Role);
            adminRoleQuery.equalTo(NAME, ADMIN_ROLE);
            return adminRoleQuery.first();

    }).then(function (role) {
        console.log("@query Admin Role: " + JSON.stringify(role));

        //Admin Role

        var adminQuery = role.getUsers().query();
        adminQuery.equalTo(USERNAME, user.get(USERNAME));
        return adminQuery.first();

    }).then(function (user) {
        console.log("@query admin users: " + JSON.stringify(user));

        //Check if we found the user in the admin role
        if (user){
            //We found the user in the admin role
        } else {
            //Still didn't find the user in a role, just assume they are customers

    }, function(error){



response.success() terminates any in-progress asynch calls, but it doesn't itself terminate the cloud code. What's happening in the posted code, I think, is that success() gets invoked, then the then of the current promise runs (which affects your log, but nothing else).

We could do a few things to better organize the code under its current approach, but it would be better still to change the approach altogether. There's no need to enumerate the roles in code to see what roles a user has. Consider this:

// return a promise that's fulfilled with any Parse.Role which has user in the 'users' relation
function getUserRoles(user) {
    var query = new Parse.Query(Parse.Role);
    query.equalTo('users', user);
    return query.find();

Wrapping that for cloud code is easy, too:

Parse.Cloud.define('getUserRole', function(request, response) {
    getUserRoles(request.user).then(function(roles) {
    }, function(error) {