Skip to content Skip to sidebar Skip to footer

How To Chain Functions In Parse CloudCode?

I've done a parse job that checks every 'X' time if 'emailSent' is false, for each user. If it is, I call a function to send a email and change the 'emailSent' to true. That works.

Solution 1:

There are a few things that need fixing in the code: (1) as a rule, use promises if you're doing more than two consecutive asynchronous things, (2) don't call Parse.Cloud.run from cloud code, it's what you call from clients who wish to invoke cloud functions, (3) style-wise, you'll go nuts trying to figure it out later on unless you break the code into small, promise-returning steps.

I've applied all three bits of advice to your code. I don't fully understand the logic as described in code and text, but hopefully I got close enough for you to make sense of it.

// using underscore js, which provides _.map below as well as loads of other useful stuff
var _ = require('underscore');

// return a promise to get the max value of id_client in the user table
function getMaxId() {
    var query = new Parse.Query(Parse.User); 
    query.descending("id_client");
    query.limit(1);
    return query.find().then(function(users) {
        return (users.length)? users[0].get("id_client") : 0;
    });
}

// return a promise for users with emailSent flag == false
function usersWithUnsentEmail() {
    var query = new Parse.Query(Parse.User);
    query.equalTo("emailSent", false);
    return query.find();
}

// return a promise to send email to the given user, and to set its 
// emailSent flag = true, and to set its clientId to the passed value
function sendEmailToUser(user, idClient) {
    return sendEmail(user.get("email")).then(function() {
        user.set("emailSent", true);
        user.set("id_client", idClient);
        return user.save();
    });
}

// return a promise to send email to the given email address via an http service
function sendEmail(email) {
    var params = {url: 'http://www.example.com/sendemail.php', params: {email : email} };
    return Parse.Cloud.httpRequest(params);
}


Parse.Cloud.job("test", function(request, response) {
    // Set up to modify user data
    Parse.Cloud.useMasterKey();

    var maxIdClient;
    getMaxId().then(function(result) {
        maxIdClient = result;
        return usersWithUnsentEmail();
    }).then(function(users) {
        var emailPromises = _.map(users, function(user) {
            return sendEmailToUser(user, maxIdClient);
        });
        return Parse.Promise.when(emailPromises);
    }).then(function(results) {
        response.success(results);
    }, function(error) {
        response.error(error);
    });
});

EDIT - we're kind of working on logic here particular to the app, as opposed to the concept of promises, but here goes anyway. To restate the functional requirement: We want a job to find users who have not yet been recorded in another database, represented by a flag called "emailSent". Our goal is to assign these users a unique id, and send their info (for now, we'll say email address and that id) via email to some fixed destination.

So

// getMaxId() from above is almost ready, except the minimum id_client
// value is 20000, so change the line that set this to:
return (users.length)? users[0].get("id_client") : 20000;

// usersWithUnsentEmail() from above is fine
// delete sendEmailToUser() since we're not doing that

// change sendEmail() to take an array of users to be conveyed to
// the other database. Send email about them, then change each user's
// emailSent status and save them
function sendEmail(users) {
    var params = {url: 'http://www.example.com/sendemail.php', params: {users : JSON.stringify(users)} };
    return Parse.Cloud.httpRequest(params).then(function() {
        _.each(users, function(user) {user.set("emailSent", true);});
        return Parse.Object.saveAll(users);
    });
}

// add a function that takes an array of users, updates their
// id_client to be a new, unique value, and sends mail about them
// to a remote server
function synchUsers(users, idMax) {
    _.each(users, function(user) {
        user.set("id_client", idMax);
        idMax += 1;
    });
    return sendEmail(users);
}

// update the job taking all this into account
Parse.Cloud.job("test", function(request, response) {
    // Set up to modify user data
    Parse.Cloud.useMasterKey();

    var maxIdClient;
    getMaxId().then(function(result) {
        maxIdClient = result;
        return usersWithUnsentEmail();
    }).then(function(users) {
        return synchUsers(users, maxIdClient+1);
    }).then(function(results) {
        response.success(results);
    }, function(error) {
        response.error(error);
    });
});

Post a Comment for "How To Chain Functions In Parse CloudCode?"