如何在 Parse CloudCode 中链接函数?

How to chain functions in Parse CloudCode?

我已经完成了一个解析工作,每 "X" 次检查每个用户的 "emailSent" 是否为假。如果是,我调用一个函数来发送电子邮件并将 "emailSent" 更改为 true。这样可行。 我的问题是函数 "getMaxId"。我需要 return maxid 值来更改每个用户 "id_client" 列,但我不知道如何。我已经试过了,但没有用。这是什么都没有写:"console.log("写点东西ggg"); "

这是代码...

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. 获取带有标志 sentEmail=false 的所有用户。
  2. 对于每个用户,getMaxId(此 return 是所有用户的实际最大 "id_client" 值)。
  3. 将 sentEmail 的值更改为 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);
});
});

我已经用标记 "sentEmail" = false 和实际最大 id_client 为 20001 的 2 个用户进行了测试 结果:

  1. 已正确更改发送电子邮件标志。
  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) 通常,如果您要执行两个以上的连续异步操作,使用 promises,(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);
    });
});