如何在解析CloudCode中链接功能? [英] How to chain functions in Parse CloudCode?

查看:72
本文介绍了如何在解析CloudCode中链接功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经完成了一个解析工作,该检查工作针对每个用户,每隔"X"次检查"emailSent"是否为假.如果是的话,我调用一个函数来发送电子邮件,并将"emailSent"更改为true.那个有效. 我的问题是函数"getMaxId".我需要返回maxid值来更改每个用户的"id_client"列,但我不知道如何.我已经尝试过了,但是没有用.这什么也没写:"console.log(" Write somethingggg);"

这是代码...

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

  var texto = "New verified emails:\n\t";
  // Query for all users
  var query = new Parse.Query(Parse.User);
  //query.equalTo("emailVerified", true);
  query.equalTo("emailSent", false);
  query.each(function(user) {

  user.set("emailSent", true);
user.save(); 
var datos = user.get("email")+"\n";
texto=texto+datos;

Parse.Cloud.run("getMaxId", {},{
success: function(results) {
console.log("Write somethingggg"); 
    user.set("id_client", "gofoadasda");
    user.save();
    var datos = user.get("id_client")+"\n";
    //console.log("id_client: "+datos);
    response.success();


},
error: function(results, error) {
  response.error(errorMessageMaker("running chained function",error));
}

  }).then(function() {

// Set the job's success status


  }, function(error) {
    // Set the job's error status
    status.error("Uh oh, something went wrong.");

});
    Parse.Cloud.run("sendEmail",{
    success: function(results) {

        response.success(results);

    },
error: function(results, error) {
  response.error(errorMessageMaker("running chained function",error));
}

  });

  }).then(function() {

    // Set the job's success status
    console.log("texto: "+texto);
    status.success("Migration completed successfully.");
   }, function(error) {
      // Set the job's error status
      status.error("Uh oh, something went wrong.");
    });
  });
  Parse.Cloud.define("sendEmail", function(request, response) {
      Parse.Cloud.httpRequest({
            url: 'http://www.example.com/sendemail.php',
            params: {
        email : 'email@email.com'
        },
        success: function(httpResponse) {
        console.log(httpResponse.text);
        },
        error: function(httpResponse) {
    console.error('Request failed with response code ' + httpResponse.status);
}
});
  });

  Parse.Cloud.define("getMaxId", function(request,response) {
      var query = new Parse.Query(Parse.User); 
      query.descending("id_client");  
      query.find({
          success: function(results) {
        var idmax=results[0].get("id_client")
        console.log("idmax: "+idmax);
        response.success(idmax);

    },
    error: function() {
        response.error(" is an error");
    }
      });

  });

第一次更改:

在@danh帮助之后,我尝试做我需要的事情,更改了一些代码:

重要提示:id_client是一个int值,它对于每个用户都是唯一的,它从20000开始.

  1. 使用标记sendEmail = false获取所有用户.
  2. 对于每个用户,请使用getMaxId(这将返回所有用户的实际最大"id_client"值).
  3. 将sendEmail的值更改为true,将用户id_client设置为实际的最大id.
  4. 发送电子邮件.

新代码(sendEmail没有更改):

var _ = require('underscore');

// return a promise to get the max value of id_client in the user table
function getMaxId(user) {
    var query = new Parse.Query(Parse.User); 
    //return query.count();
    query.descending("id_client");
    query.limit(1);
    return query.find().then(function(users) {
        if(users[0].get("id_client")<20000){ //No users yet.
            user.set("id_client", 20000);  //First id:20000
            user.save();
            return 20000;
        }
        else{ //There are users. Get the maxId and increment +1.
            user.set("id_client", users[0].get("id_client")+1);
            user.save();
            return (users.length)? users[0].get("id_client")+1 : 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
 function sendEmailToUser(user) {
     return sendEmail(user.get("email")).then(function() {
         user.set("emailSent", true);
         return user.save();
     });
 }
Parse.Cloud.job("test", function(request, response) {
// Set up to modify user data
Parse.Cloud.useMasterKey();

usersWithUnsentEmail().then(function (users){
    var emailPromises = _.map(users, function(user) {
        //what I understand is that here, for each user, we call getMaxId, getting the actual max id_client, and then, we pass it to "sendEmailToUser".
        return getMaxId(user).then(function(max){
            return sendEmailToUser(user);
        });
    });
    return Parse.Promise.when(emailPromises);//This means that we have looped all users, is it?
}).then(function(results) {
    response.success(results);
}, function(error) {
    response.error(error);
});
});

我已经用2位用户进行了测试,其标志为"sentEmail" = false,实际的最大id_client为20001 结果:

  1. sentEmail标志已正确更改.
  2. 正确发送了2封电子邮件.
  3. 此处错误:两个用户的id_client都更改为20002.它必须是20002和20003.

登录解析:

I2015-04-22T09:44:13.433Z] v90: Ran job test with:
  Input: {}
  Result: undefined
E2015-04-22T09:44:29.005Z] v90: Ran job test with:
  Input: {}
  Failed with: Error: Job status message must be a string
    at updateJobMessageAndReturn (<anonymous>:790:7)
    at Object.success (<anonymous>:828:9)
    at main.js:217:18
    at e (Parse.js:3:8736)
    at Parse.js:3:8185
    at Array.forEach (native)
    at Object.x.each.x.forEach [as _arrayEach] (Parse.js:1:661)
    at c.extend.resolve (Parse.js:3:8136)
    at Parse.js:3:8815
    at e (Parse.js:3:8736)

我们需要他们的电子邮件以及我们将为其分配的id_client.

可能是因为我没有很好地解释,该电子邮件将不会发送到用户电子邮件,该电子邮件将发送到我在sendemail.php脚本中确定的电子邮件,并且始终是一样.

我将解释:您在家中有一个本地数据库,然后解析数据库.调用此Parse.job时,它将向您发送一封电子邮件(php的电子邮件),其中包含电子邮件列表和每个用户的id_client更新.现在,您可以使用收到的电子邮件信息来手动更新本地数据库.

因此,由于这个原因,最好在所有更新结束时仅发送一封电子邮件. (我之所以这么说,是因为我有很多问题,但仍想了解cloudCode的工作原理...)

解决方案

代码中需要修复一些问题:(1)通常,使用诺言超过两个连续的异步事物,(2)不要从云代码中调用Parse.Cloud.run ,这是您从希望调用云函数的客户端调用的东西,(3)在样式上,除非您将代码分解成小的,可以兑现承诺的小步骤,否则您将不遗余力地尝试解决.

我已将所有三点建议应用于您的代码.我不完全理解代码和文本中描述的逻辑,但是希望我已经足够亲近以使您理解它.

// 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);
    });
});

编辑-我们在这里正在研究特定于应用程序的逻辑,而不是承诺的概念,但是无论如何这里都可以进行.重述功能要求:我们想要一项工作来查找尚未记录在另一个数据库中的用户,该用户由一个名为"emailSent"的标志表示.我们的目标是为这些用户分配一个唯一的ID,然后通过电子邮件将其信息(此刻,我们称为电子邮件地址和ID)发送到某个固定的目的地.

所以

// 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);
    });
});

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. My problem is with the function "getMaxId". I need to return the maxid value to change each user "id_client" column, but I don't know how. I've tried this but it doesn't work. This is writing nothing: "console.log("Write somethingggg"); "

Here is the code...

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

  var texto = "New verified emails:\n\t";
  // Query for all users
  var query = new Parse.Query(Parse.User);
  //query.equalTo("emailVerified", true);
  query.equalTo("emailSent", false);
  query.each(function(user) {

  user.set("emailSent", true);
user.save(); 
var datos = user.get("email")+"\n";
texto=texto+datos;

Parse.Cloud.run("getMaxId", {},{
success: function(results) {
console.log("Write somethingggg"); 
    user.set("id_client", "gofoadasda");
    user.save();
    var datos = user.get("id_client")+"\n";
    //console.log("id_client: "+datos);
    response.success();


},
error: function(results, error) {
  response.error(errorMessageMaker("running chained function",error));
}

  }).then(function() {

// Set the job's success status


  }, function(error) {
    // Set the job's error status
    status.error("Uh oh, something went wrong.");

});
    Parse.Cloud.run("sendEmail",{
    success: function(results) {

        response.success(results);

    },
error: function(results, error) {
  response.error(errorMessageMaker("running chained function",error));
}

  });

  }).then(function() {

    // Set the job's success status
    console.log("texto: "+texto);
    status.success("Migration completed successfully.");
   }, function(error) {
      // Set the job's error status
      status.error("Uh oh, something went wrong.");
    });
  });
  Parse.Cloud.define("sendEmail", function(request, response) {
      Parse.Cloud.httpRequest({
            url: 'http://www.example.com/sendemail.php',
            params: {
        email : 'email@email.com'
        },
        success: function(httpResponse) {
        console.log(httpResponse.text);
        },
        error: function(httpResponse) {
    console.error('Request failed with response code ' + httpResponse.status);
}
});
  });

  Parse.Cloud.define("getMaxId", function(request,response) {
      var query = new Parse.Query(Parse.User); 
      query.descending("id_client");  
      query.find({
          success: function(results) {
        var idmax=results[0].get("id_client")
        console.log("idmax: "+idmax);
        response.success(idmax);

    },
    error: function() {
        response.error(" is an error");
    }
      });

  });

FIRST CHANGES:

After @danh help, I tried to do what I need, changing some code:

Important: id_client is a int value which it's unique for each user, it starts at 20000.

  1. get all the users with the flag sentEmail=false.
  2. For each of those users, getMaxId (this returns the actual max "id_client" value for all the users).
  3. Change value of sentEmail to true, set user id_client to the actual max id.
  4. Send email.

New code (sendEmail has no changes):

var _ = require('underscore');

// return a promise to get the max value of id_client in the user table
function getMaxId(user) {
    var query = new Parse.Query(Parse.User); 
    //return query.count();
    query.descending("id_client");
    query.limit(1);
    return query.find().then(function(users) {
        if(users[0].get("id_client")<20000){ //No users yet.
            user.set("id_client", 20000);  //First id:20000
            user.save();
            return 20000;
        }
        else{ //There are users. Get the maxId and increment +1.
            user.set("id_client", users[0].get("id_client")+1);
            user.save();
            return (users.length)? users[0].get("id_client")+1 : 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
 function sendEmailToUser(user) {
     return sendEmail(user.get("email")).then(function() {
         user.set("emailSent", true);
         return user.save();
     });
 }
Parse.Cloud.job("test", function(request, response) {
// Set up to modify user data
Parse.Cloud.useMasterKey();

usersWithUnsentEmail().then(function (users){
    var emailPromises = _.map(users, function(user) {
        //what I understand is that here, for each user, we call getMaxId, getting the actual max id_client, and then, we pass it to "sendEmailToUser".
        return getMaxId(user).then(function(max){
            return sendEmailToUser(user);
        });
    });
    return Parse.Promise.when(emailPromises);//This means that we have looped all users, is it?
}).then(function(results) {
    response.success(results);
}, function(error) {
    response.error(error);
});
});

I've tested this with 2 users with the flag "sentEmail" = false and actual max id_client was 20001 Result:

  1. sentEmail flags changed correctly.
  2. 2 emails sent correctly.
  3. Error here: id_client for both users changed to 20002. It has to be 20002 and 20003.

Logs in parse:

I2015-04-22T09:44:13.433Z] v90: Ran job test with:
  Input: {}
  Result: undefined
E2015-04-22T09:44:29.005Z] v90: Ran job test with:
  Input: {}
  Failed with: Error: Job status message must be a string
    at updateJobMessageAndReturn (<anonymous>:790:7)
    at Object.success (<anonymous>:828:9)
    at main.js:217:18
    at e (Parse.js:3:8736)
    at Parse.js:3:8185
    at Array.forEach (native)
    at Object.x.each.x.forEach [as _arrayEach] (Parse.js:1:661)
    at c.extend.resolve (Parse.js:3:8136)
    at Parse.js:3:8815
    at e (Parse.js:3:8736)

EDITED:

We need their email and the id_client that we will assign them.

May be I haven't explained well, the email won't be sent to the user email, the email will be sent to a email that I've determined in the sendemail.php script, and it will be always the same.

I'll explain: You have a local database at home, and parse database. When this Parse.job is called, it will send an email to you (email of php) with a list of the email and the id_client of each user updated. Now you can manually update your local database with the email received info.

So, for this reason, it will be better to send only one email, at the end of all the updates. (I didn't say that because I had a lot of problems yet trying to understand how cloudCode works...)

解决方案

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);
    });
});

这篇关于如何在解析CloudCode中链接功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆