如何在 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 开始。
- 获取带有标志 sentEmail=false 的所有用户。
- 对于每个用户,getMaxId(此 return 是所有用户的实际最大 "id_client" 值)。
- 将 sentEmail 的值更改为 true,将用户 id_client 设置为实际的最大 ID。
- 发送电子邮件。
新代码(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 个用户进行了测试
结果:
- 已正确更改发送电子邮件标志。
- 2 封电子邮件已正确发送。
- 此处错误: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);
});
});
我已经完成了一个解析工作,每 "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 开始。
- 获取带有标志 sentEmail=false 的所有用户。
- 对于每个用户,getMaxId(此 return 是所有用户的实际最大 "id_client" 值)。
- 将 sentEmail 的值更改为 true,将用户 id_client 设置为实际的最大 ID。
- 发送电子邮件。
新代码(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 个用户进行了测试 结果:
- 已正确更改发送电子邮件标志。
- 2 封电子邮件已正确发送。
- 此处错误: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);
});
});