Advanced Guides
升级到Parse 3.1版本的技术要点与开发者指南
19 分
为您的应用程序提供更多功能,使用 parse server 3 1 介绍 parse 社区最近发布了版本 https //docs parseplatform org/parse server/guide/ 此次更新清理了云代码语法:它更容易利用 es6 的 async 和 await 结构。 此外,与使用 parse 相关的一些特性被去掉,例如,云函数简单地返回一个 promise,而不是在响应对象上使用 错误 错误 或 成功 成功 消息。 您可以在 back4app 的仪表板上轻松升级您的应用程序。本指南将演示如何升级您的代码以利用 3 1 的新功能。 要遵循本指南,欢迎您查看提供的 https //github com/back4app/parse server break changes 。 这是由 https //github com/considine , https //koptional com/ 的首席开发人员撰写的客座教程。 目标 将您的 back4app parse server 更新到 3 1,并相应地迁移您的云代码。 先决条件 要完成本教程,您需要: ° 一个现有的使用 parse server 2 x 的 back4app 应用程序 ° 请遵循 https //www back4app com/docs/get started/new parse app 以了解如何在 back4app 上创建应用。 更改摘要 最显著的变化如下: 1\ 云代码与 parse sdk 2 x 一起运行。 之前,云代码与 parse sdk 1 x 一起运行。随着 parse server 3 1,它运行 parse sdk 2 x。 查看 https //github com/parse community/parse sdk js/releases 以更好地理解这意味着什么。这个主要版本的提升主要涉及错误修复。它还添加了 https //parseplatform org/parse sdk js/api/2 1 0/parse query html#containedby 和 https //parseplatform org/parse sdk js/api/2 1 0/parse query html#includeall 查询方法,以及使用 includes 获取对象的能力。 2 聚合更新 自 parse 2 7 1 起,您可以在查询上使用 https //parseplatform org/parse sdk js/api/2 1 0/parse query html#aggregate 方法。这使您能够更好地利用底层数据库。现在, https //parseplatform org/parse sdk js/api/2 1 0/parse query html#aggregate 的语法在 parse query parse query 上已更新。 您可以使用两个阶段执行查询: match match 和 group group 阶段。 1 // 匹配名称为 foo 的用户,并按其 objectid 分组 2 const pipeline = \[{ group { objectid {} } }, { match { name 'foo' } }]; 3 4 var query = new parse query("person"); 5 query aggregate(pipeline) 之前,您不需要在管道对象中包含 pipeline 键。由于底层 api,您现在必须明确包含 pipeline 键。其值应为一个或两个阶段的数组,包含 group group 和 match match 查看 https //docs parseplatform org/js/guide/#aggregate 以获取更具体的示例。 3 底层优化 一些底层优化已经完成。例如, https //parseplatform org/parse sdk js/api/2 1 0/parse livequery html 将获取类级权限 (clps) 以及数据,以防止双重数据库访问。 4\ parse 重置电子邮件 当请求密码重置邮件时,即使该邮件未被保存,服务器也会返回成功。此外,当用户的电子邮件被重置时,密码重置令牌会过期。 5\ 云触发器更新 通过此版本,您可以在同一对象之间共享数据, https //docs parseplatform org/cloudcode/guide/#beforesave triggers 和 https //docs parseplatform org/cloudcode/guide/#aftersave triggers 触发器。例如: 1 parse cloud beforesave('comment', async request => { 2 request context = { 3 foo 'bar' 4 }; 5 }); 6 7 parse cloud aftersave('comment', async request => { 8 console log(request context foo); //bar 9 }); 您可以通过点击查看官方 parse 3 1 更新日志中的 parse server 变更 https //github com/parse community/parse server/blob/alpha/changelog md 6\ livequery 改进 parse livequery 客户端允许您订阅查询,并在服务器发送更新时接收更新。传统查询由客户端执行一次,因此这对于消息传递等情况非常有帮助。 使用 back4app,您还可以 https //www back4app com/docs/platform/parse server live query example 。 随着 3 x 的发布,parse 社区改善了 livequery 的系统 https //docs parseplatform org/js/guide/#security for other objects 。 您现在可以将会话令牌传递给实时查询的订阅方法,parse 服务器将仅管理返回该用户可以访问的结果。例如,用户可能对某些‘消息’具有读/写访问权限,但并非所有消息。 1 let query = new parse query('message'); 2 // you can get session token with 3 // parse user current() getsessiontoken() when logged in 4 let subscription = client subscribe(query, sessiontoken); 上述代码将自动订阅用户可以访问的所有消息,减轻了您查询特定消息的责任。 更改的主要部分涉及云代码的处理。有关此内容,请参阅下面的迁移指南。 1 对齐技术基础 我们将以一个使用2 x版本的示例云项目开始。这样我们可以导航到适当的语法更改。你可以看到 https //github com/back4app/parse server break changes 作为这个示例项目的参考。 如果你熟悉async和await,你可以跳过这一部分。 javascript中异步代码的演变大致如下: https //developer mozilla org/en us/docs/glossary/callback function https //developer mozilla org/en us/docs/web/javascript/reference/global objects/promise https //developer mozilla org/en us/docs/web/javascript/reference/statements/async function 任何现代javascript应用程序都可能使用这三者。回调函数涉及将一个函数作为参数传递给另一个函数。这个第二个函数可以在某个时刻执行第一个函数。 1 // callbacks 2 // executes callback function after waiting 100 milliseconds 3 settimeout(function() { 4 alert('my callback function'); 5 }, 100); 回调是必不可少的,但在链接多个回调时可能会显得笨拙。具体来说,嵌套多个层次可能难以阅读,错误处理也很困难。因此在es2015中引入了promise。 1 // promises 2 // executes several promises in a row with no significant nesting 3 const mypromise = new promise(function(resolve, reject) { 4 settimeout(function() { 5 if (math random() < 0 2) reject(new error('random failure!')); 6 resolve('finished'); 7 }, 100); 8 }); 9 10 // executes this promise 4 times and catches errors involved 11 mypromise 12 then(() => mypromise) 13 then(() => mypromise) 14 then(() => mypromise) 15 then(() => mypromise) 16 catch(e => console log(e)); promise提高了异步编程的可读性。它们还使管道更加明确。但在 https //www ecma international org/ecma 262/8 0/#sec async function definitions 中,使用async / await构造取得了更大的进步。您的代码现在可以等待promise的结果,而无需依赖then / catch块(这也可能变得难以阅读)。 1 // using the definition of mypromise from the above code 2 async function foo() { 3 try { 4 let result = await mypromise; 5 result = await mypromise; 6 result = await mypromise; 7 } catch (e) { 8 console log(e); 9 } 10 } 也许对于一个非常简单的例子,这看起来并不比普通的promise更优雅。但等待异步函数的结果往往正是我们想要做的。因此,它确实优化了我们代码的可读性。 对 async/await 的支持 如前所述,async/await 被包含在 https //www ecma international org/ecma 262/8 0 (es8)。对于服务器代码,版本控制几乎不是问题,因为您可以更新到 https //node green/#es2017 请放心,back4app 的环境支持最近的稳定版本。对于浏览器代码,像 https //babeljs io/ 的转译器将生成与使用 async / await 的 es2016 兼容的代码,并在现代浏览器中工作。 2 以不同的方式思考您的代码 cloud code 的主要变化涉及开发者所做的与库所做的之间的区别。以前,您会显式管理响应。由于大多数 cloud code 将异步执行 进行数据库查询和写入 返回一个 promise 更有意义,从而减少样板代码。 cloud 函数的直觉是编写服务器端代码时涉及的设置和配置最小化。此版本体现了这一理念;在重构和创建新函数时请记住这一点。 为了展示 cloud code 函数在 parse server 3 1 中的工作原理,我们重写了一个来自迁移前版本的功能性 cloud code 示例。您可以通过点击 https //github com/back4app/parse server break changes/tree/step 1 相同的 cloud code 函数在 parse 3 1 中如下所示。 1 // cloud code before migration 2 // full code found in link above 3 const post = 'post'; 4 parse cloud define('posts\ get', function(request, response) { 5 // needs a post id 6 return new parse query(post) 7 get(request params id, { usemasterkey true }) 8 then(post => { 9 response success(post); 10 }) 11 catch(e => { 12 response error({ message e message }); 13 }); 14 }); 3 添加所有异步标记 任何使用 await 的函数必须声明为 async 修饰符。这个简单的重构将把 async 附加到所有云函数上。它还将用 https //developer mozilla org/en us/docs/web/javascript/reference/functions/arrow functions 替换它们,因为在这种情况下它们更简洁(也是更新后的官方 parse 指南所使用的)。 1 // snippet of step 2 code refactoring see full code 2 // here in the link at the top of this step 3 const post = 'post'; 4 const comment = 'comment'; 5 6 parse cloud define('posts\ get', async (request) => { 7 // needs a post id 8 return new parse query(post) 9 get(request params id, { usemasterkey true }); 10 } 您的代码在重构后将看起来像 https //github com/back4app/parse server break changes/tree/step 2 重构后 到目前为止没有什么疯狂的。在下一步中,我们将为这个变化获得物有所值。 4 移除对响应的引用,使用 await 您的代码看起来像 https //github com/back4app/parse server break changes/tree/step 3 在这个重构之后 这一步有点棘手。我们需要: 删除对‘response’变量的所有引用,改为返回一个promise 在多个查询/保存函数的情况下,等待响应 查看评论创建方法以了解这是如何完成的 1 // snippet of step 3 code refactoring see full code 2 // here in the link at the top of this step 3 parse cloud define('comment\ create', async request => { 4 // post should have text and should have a user and a post id 5 if (!request user) { 6 throw new error('unauthenticated!'); 7 } 8 9 if (!request params text) { 10 throw new error('a comment needs text!'); 11 } 12 if (!request params post id) { 13 throw new error('a comment needs a post!'); 14 } 15 16 // get the post 17 18 const post = await new parse query(post) get(request params post id, { 19 usemasterkey true 20 }); 21 return new parse object(comment, { 22 text request params text, 23 user request user, 24 post post 25 }) save(null, { usemasterkey true }); 26 }); 注意: 现在抛出一个javascript错误,而不是调用response error。parse将处理将其转换为响应的过程。 删除‘帖子’或‘评论’涉及先获取对象,然后销毁它。通过使用‘await’,销毁方法可以在块外访问保存的对象。 这完成了迁移所需的所有重构。也就是说,如果你做到这一步,恭喜你!你的代码将在 back4app parse 3 1 上运行! 5 高级技巧(可选) 以下更改是可选的,但可以显著缩短你的代码。我发现它们减少了样板代码。 你可能注意到很多手动检查参数或经过身份验证的用户。这些确保不会发生奇怪的行为。例如,我们已经决定我们的‘post’对象需要文本,因此如果没有传递‘text’参数,该对象将会在没有它的情况下被保存。防止这种情况的一种方法是检查是否传递了文本。 但是手动检查可能会耗时且不优雅。在这一部分,我们利用 https //developer mozilla org/en us/docs/web/javascript/reference/operators/destructuring assignment 来隐式完成这些检查。 如果你不知道什么是解构,你应该查看上面的文档。但简而言之,它允许你用非常简洁的语法将对象的属性转换为变量。 1 // this 2 var obj = { 3 hi true, 4 bye false 5 }; 6 var hi = obj hi; 7 var bye = obj bye; 8 9 // is equivalent to this 10 var obj = { 11 hi true, 12 bye false 13 }; 14 var { hi, bye } = obj; 15 16 console log(hi); 17 // true 18 console log(bye); 19 // false 解构赋值比手动赋值更简洁。它还允许你即时声明参数变量,这很好 1 parse cloud define('posts\ get', async ({ params { id } }) => { 2 // id is declared 3 }); 当与 es2015 语法结合使用时,我们可以优化我们的参数检查。 我们可以这样做 1 // iterates through object's keys makes sure, for each key, the value is set 2 const assertparams = parameter obj => { 3 for (var key of object keys(parameter obj)) { 4 if (typeof parameter obj\[key] === 'undefined') 5 throw new error(`missing parameter ${key}`); 6 } 7 }; 8 9 var obj = { 10 hi true, 11 bye false 12 }; 13 var { hi, undef, bye } = obj; // undef will be undefined 14 var check 1 = { hi, bye }; 15 var check 2 = { hi, undef }; 16 17 // check = { hi true, no undefined } 18 assertparams(check 1); // passes 19 assertparams(check 2); // throws error 所以对于我们的 parse 代码,我们可以这样做: 1 // snippet of advanced code refactoring see full code 2 // here in the link at the top of this step 3 parse cloud define('posts\ delete', async ({ user, params { id } }) => { 4 // makes sure user is authenticated, and id parameter is passed 5 assertparams({ user, id }); 6 const post = await new parse query(post) get(id, { 7 usemasterkey true 8 }); 9 return post destroy({ usemasterkey true }); 10 }); 如果这让你感到畏惧,不用担心。这个 https //github com/back4app/parse server break changes/tree/step advanced 示例可能会有所帮助。 简而言之,‘assertparams’ 是一个实用函数,用于在值未定义时抛出错误。我们可以通过结合对象解构和 es2015 对象初始化来一次性检查参数。 这消除了八到九个手动检查,这在一段时间后会变得不太美观。 6 在 back4app 上升级 一旦您迁移了代码,您还必须做两件事才能在 back4app 上运行它。 升级您的 back4app 服务器版本 上传您的新云代码。 我之前简要提到过第一步。您需要做的就是登录 back4app 并进入您应用的仪表板。从那里,只需在左侧选择“服务器设置”,然后在“管理 parse 服务器”卡上点击“设置”按钮。然后您可以选择 parse server 3 1 1 单选按钮并点击“保存”。 最后但同样重要的是,您可以通过 https //blog back4app com/2017/01/20/cli parse server/ , 或使用手动上传通过您的仪表板上传您的代码。如果您需要更多关于此步骤的信息,请参见 https //www back4app com/docs/android/parse cloud code 。 关于发布新版本的说明 如果您的代码很复杂,最好在执行这两个步骤之前进行一些测试。back4app 有一些关于如何做到这一点的指南,您可以在 https //www back4app com/docs/advanced guides/parse cloud code testing 和 https //www back4app com/docs/cloud code functions/unit tests 找到。 最后,重要的是要注意这些变化是 重大 。在 2 x parse server 上使用我们编写的代码将会失败,而在 3 1 服务器上使用 2 x 代码也会失败。因此,您必须确保在上传升级后的 cloud code 时立即升级您的 back4app 解析版本。如果您有很多用户,并且担心代码上传和版本升级稍微不同步,您可以这样做。 1 const serverversion = 2 parse coremanager get('version') === 'js1 11 1' ? 'old' 'new'; 3 4 if (serverversion === 'new') { 5 parse cloud define('posts\ get', async ({ params { id } }) => { 6 assertparams({ id }); 7 // needs a post id 8 return new parse query(post) get(id, { 9 usemasterkey true 10 }); 11 }); 12 } else if (serverversion === 'old') { 13 // old definition here 14 } 这段代码动态地确定版本并根据此定义 cloud 函数。上传后,您将更改为 3 1,然后可以重新上传删除旧部分的代码。最初包含检查可以确保您的代码不会崩溃。由于您可以在几秒钟内升级和上传,因此通常没有必要。 结论 在本指南中,我们简单演示了如何将您的 cloud code 迁移到 parse 3 1 版本。记得在进行这些更改后将您的 back4app 版本提升到 3 1。 同样重要的是,本指南演示了 parse 3 1 所利用的改进语法。我们的重构将代码库从约 160 行减少到约 90 行,并使其更易读。对于实际应用,这将带来回报。