云代码使用指南

云代码,就是运行在云端,而非客户端的函数代码。

云代码是构建在ParseServer中的,默认云代码的入口文件是./cloud/main.js

云函数

就像你在代码中调用别人的函数一样,调用云函数就是调用云端的函数。

假设我们在云代码文件中定义一个averageStart函数,功能是通过传入的电影名返回评论数量:

  1. Parse.Cloud.define("averageStars", function(request, response) {
  2. const query = new Parse.Query("Review");
  3. query.equalTo("movie", request.params.movie);
  4. .find()
  5. .then((results) => {
  6. let sum = 0;
  7. for (let i = 0; i < results.length; ++i) {
  8. sum += results[i].get("stars");
  9. }
  10. response.success(sum / results.length);
  11. })
  12. .catch(() => {
  13. response.error("movie lookup failed");
  14. });
  15. });

然后,在客户端可以这样调用averageStarts方法:

  1. Parse.Cloud.run('averageStars', { movie: 'The Matrix' }).then(function(ratings) {
  2. // ratings = 4.5
  3. });

Cloud Jobs

云作业,当你需要定义一个执行时间很长的云函数,并且不用等待它响应,你就可以使用云作业。我们来定义一个云作业:

  1. Parse.Cloud.job("myJob", function(request, status) {
  2. // 请求参数
  3. const params = request.params;
  4. //请求头
  5. const headers = request.headers;
  6. // get the parse-server logger
  7. const log = request.log;
  8. // 更新作业状态
  9. status.message("I just started");
  10. doSomethingVeryLong().then(function(result) {
  11. //作业完成
  12. status.success("I just finished");
  13. })
  14. .catch(function(error) {
  15. // 作业失败
  16. status.error("There was an error");
  17. });
  18. });

云作业需要提供master key才能调用,你可以通过REST API调用:

  1. curl -X POST -H 'X-Parse-Application-Id: appId' -H 'X-Parse-Master-Key: masterKey' https://my-parse-server.com/parse/jobs/myJob

触发器

注册对应class表的钩子后,对应的事件将触发对应的钩子。

在下面触发器中,你需要注意,如果你要注册ParseServer预定义的class表,比如User表,你不应该给第一个参数传入字符(“Review”),而是传入对象,比如Parse.User

beforeSave

当云端收到保存某对象的请求后,在保存某对象前,会触发此方法。

若在方法中调用response.error,对象将不会被保存,客户端返回错误;若在方法中调用response.success,对象将会被成功保存。

  1. //注册Review表的beforeSave触发器,有对象被保存前,触发此方法。
  2. Parse.Cloud.beforeSave("Review", function(request, response) {
  3. if (request.object.get("stars") < 1) {
  4. response.error("少于1星,不能获取");
  5. } else if (request.object.get("stars") > 5) {
  6. response.error("多余5星,不能获取");
  7. } else {
  8. response.success();
  9. }
  10. });

我们还可以在函数中修改对象,比如,将评论内容限制在140字以内:

  1. Parse.Cloud.beforeSave("Review", function(request, response) {
  2. var comment = request.object.get("comment");
  3. if (comment.length > 140) {
  4. // Truncate and add a ...
  5. request.object.set("comment", comment.substring(0, 137) + "...");
  6. }
  7. response.success();
  8. });

afterSave

在某对象保存后,会触发此方法。

假设你要在一条文章评论保存后,更新文章评论数量的字段:

  1. Parse.Cloud.afterSave("Comment", function(request) {
  2. const query = new Parse.Query("Post");
  3. query.get(request.object.get("post").id)
  4. .then(function(post) {
  5. post.increment("comments");
  6. return post.save();
  7. })
  8. .catch(function(error) {
  9. console.error("Got an error " + error.code + " : " + error.message);
  10. });
  11. });

不管上面方法中有没有报错,客户端都会返回成功。

beforeDelete

在对象被删除前,会触发此方法。

假设你有一个相册应用,当用户发起了删除某个相册的操作,需要先检查这个相册里有没有照片,如果有就不允许删除,可以这样:

  1. Parse.Cloud.beforeDelete("Album", function(request, response) {
  2. const query = new Parse.Query("Photo");
  3. query.equalTo("album", request.object);
  4. query.count()
  5. .then(function(count) {
  6. if (count > 0) {
  7. response.error("Can't delete album if it still has photos.");
  8. } else {
  9. response.success();
  10. }
  11. })
  12. .catch(function(error) {
  13. response.error("Error " + error.code + " : " + error.message + " when getting photo count.");
  14. });
  15. });

若在方法中调用response.error,对象将不会被保存,客户端返回错误;若在方法中调用response.success,对象将会被成功保存。

afterDelete

在对象被删除后,会触发此方法。

假设你在一篇博文被删除后,同时删除这篇博文的所有评论,可以这样:

  1. Parse.Cloud.afterDelete("Post", function(request) {
  2. const query = new Parse.Query("Comment");
  3. query.equalTo("post", request.object);
  4. query.find()
  5. .then(Parse.Object.destroyAll)
  6. .catch(function(error) {
  7. console.error("Error finding related comments " + error.code + ": " + error.message);
  8. });
  9. });

beforeFind

在find查询进入后,会触发此方法。

如果你想为查询加上额外的限制、条件、你可以注册这个触发器。

例子

  1. // 属性
  2. Parse.Cloud.beforeFind('MyObject', function(req) {
  3. let query = req.query; // Parse.Query
  4. let user = req.user; // user
  5. let triggerName = req.triggerName; // beforeFind
  6. let isMaster = req.master; // 如果使用查询masterKey
  7. let isCount = req.count; // 如果是count查询
  8. let logger = req.log; //logger
  9. let installationId = req.installationId; // installationId
  10. });
  11. // 限制返回字段
  12. Parse.Cloud.beforeFind('MyObject', function(req) {
  13. let query = req.query; // Parse.Query
  14. query.select(['key1', 'key2']);
  15. });
  16. // 异步支持
  17. Parse.Cloud.beforeFind('MyObject', function(req) {
  18. let query = req.query;
  19. return aPromise().then((results) => {
  20. // do something with the results
  21. query.containedIn('key', results);
  22. });
  23. });
  24. // 返回一个不同的查询
  25. Parse.Cloud.beforeFind('MyObject', function(req) {
  26. let query = req.query;
  27. let otherQuery = new Parse.Query('MyObject');
  28. otherQuery.equalTo('key', 'value');
  29. return Parse.Query.or(query, otherQuery);
  30. });
  31. // 拒绝查询
  32. Parse.Cloud.beforeFind('MyObject', function(req) {
  33. // throw an error
  34. throw new Parse.Error(101, 'error');
  35. // rejecting promise
  36. return Promise.reject('error');
  37. });