Advanced Guides
Миграция Parse Server до версии 3.1: основные изменения
24 мин
больше возможностей для вашего приложения с parse server 3 1 введение сообщество parse недавно выпустило версию 3 1 parse server https //docs parseplatform org/parse server/guide/ это обновление улучшило синтаксис cloud code он стал гораздо более удобным для использования конструкций es6 async и await кроме того, некоторые особенности, связанные с использованием parse, были убраны, например, cloud функции просто возвращают promise, а не используют ошибку ошибку или успех успех сообщения в объекте response вы можете легко обновить свои приложения на back4app через свою панель управления этот гид покажет, как обновить ваш код, чтобы использовать новые функции 3 1 чтобы следовать этому руководству, вы можете ознакомиться с примером проекта предоставленным это учебник для гостей, написанный джоном консидином https //github com/considine , ведущим разработчиком в k optional https //koptional com/ цели обновить ваш back4app parse server до 3 1 и соответственно мигрировать ваш cloud code предварительные требования чтобы завершить этот учебник, вам нужно ° существующее приложение back4app, использующее parse server 2 x ° следуйте учебнику по созданию нового приложения чтобы узнать, как создать приложение на back4app сводка изменений наиболее заметные изменения следующие 1\ cloud code работает с parse sdk 2 x ранее cloud code работал с parse sdk 1 x с parse server 3 1 он работает с parse sdk 2 x посмотрите на релизы parse sdk чтобы лучше понять, что это подразумевает это значительное обновление в основном включает исправления ошибок оно также добавляет containedby и includeall методы запроса, а также возможности извлечения объекта с includes 2 агрегатное обновление с версии parse 2 7 1 вы можете использовать метод aggregate в запросе это позволяет вам немного больше использовать базу данных теперь синтаксис для метода aggregate в parse query parse query был обновлён вы можете выполнить запрос, используя два этапа match match и group group этап ранее вам не нужен был ключ pipeline в объекте pipeline из за базового api теперь вы должны явно включить ключ pipeline значение должно быть массивом из одной или двух стадий, содержащих группировка группировка и совпадение совпадение смотрите официальная документация parse для более конкретных примеров 3 оптимизации под капотом некоторые оптимизации под капотом были сделаны например, parse livequery будет извлекать разрешения на уровне класса (clp) вместе с данными, чтобы предотвратить двойной доступ к базе данных 4\ сброс электронной почты parse при запросе на сброс пароля сервер вернет успех, даже если этот адрес электронной почты не сохранен кроме того, токены сброса пароля истекают, когда адрес электронной почты пользователя сбрасывается 5\ обновление триггеров облака с этим релизом вы можете делиться данными между beforesave и aftersave триггерами на одном объекте например 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 server в официальном журнале изменений parse 3 1, нажав здесь 6\ улучшение livequery клиент parse livequery позволяет вам подписываться на запросы и получать обновления от сервера по мере их поступления традиционные запросы выполняются клиентом один раз, поэтому это очень полезно для таких случаев, как обмен сообщениями и т д с back4app вы также можете воспользоваться этой технологией https //www back4app com/docs/platform/parse server live query example с выходом версии 3 x сообщество parse улучшило систему для livequery acls 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); вышеуказанный код автоматически подпишется на все сообщения, к которым у пользователя есть доступ, освобождая вас от ответственности за запрос конкретных сообщений основная часть изменений касается того, как обрабатывается cloud code для этого смотрите руководство по миграции ниже 1 выравнивание технических основ мы начнем с примера облачного проекта, используя версию 2 x таким образом, мы сможем пройти через соответствующие изменения синтаксиса вы можете увидеть репозиторий для этого примера проекта если вы знакомы с async и await, вы можете пропустить этот раздел эволюция асинхронного кода в javascript выглядит примерно так функции обратного вызова обещания async / await любое современное приложение на 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)); промисы улучшают читаемость асинхронного программирования они также делают конвейеры более явными но еще большие шаги были сделаны в es2017 с конструкциями async / await ваш код теперь может ожидать результаты промиса, не полагаясь на блоки 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 } возможно, для очень простого примера это может показаться не более элегантным, чем простые промисы но ожидание результатов асинхронной функции часто именно то, что мы хотим сделать следовательно, это действительно оптимизирует читаемость нашего кода поддержка async/await как уже упоминалось, async/await был включен в спецификацию ecmascript 2017 (es8) для серверного кода версия не является проблемой, так как вы можете обновиться до версии node js, которая поддерживает эти функции будьте уверены, что среда back4app поддерживает последние стабильные версии для браузерного кода транспилеры, такие как babel создадут код, совместимый с es2016, который использует async / await и работает в современных браузерах 2 думайте о своем коде иначе основное изменение в cloud code заключается в том, что делает разработчик по сравнению с тем, что делает библиотека ранее вы явно управляли ответом поскольку большинство cloud code будет выполняться асинхронно выполняя запросы и записи в базу данных имеет больше смысла возвращать promise, сокращая количество шаблонного кода интуиция, стоящая за cloud функциями, заключается в том, что для написания серверного кода требуется минимальная настройка и конфигурация этот релиз воплощает эту идею; имейте это в виду, когда вы рефакторите и создаете новые функции чтобы показать, как работают функции cloud code в parse server 3 1, мы переписали функциональный пример cloud code из версии parse server до миграции вы можете найти этот код, кликнув здесь та же функция 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 ко всем облачным функциям она также заменит их на стрелочные функции так как они более лаконичны в этом случае (и что использует обновленное официальное руководство 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 } ваш код будет выглядеть как это после этого рефакторинга пока ничего необычного на следующем шаге мы получим свою выгоду от этого изменения 4 удаление ссылок на ответ, использование await ваш код будет выглядеть как это после этой рефакторинга этот шаг немного сложнее нам нужно удалить все ссылки на переменную ‘response’, возвращая вместо этого промис в случае нескольких функций запроса/сохранения, дождаться ответа посмотрите метод создания комментария, чтобы увидеть, как это делается 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 }); обратите внимание на теперь вместо вызова response error выбрасывается ошибка javascript parse будет обрабатывать преобразование этого в ответ для нас удаление ‘поста’ или ‘комментария’ включает в себя сначала получение объекта, а затем его уничтожение используя ‘await’, метод уничтожения может получить доступ к сохраненному объекту вне блока это завершает все необходимые рефакторинги для миграции то есть, если вы дойдете до этого шага, поздравляю! ваш код будет работать на back4app parse 3 1! 5 продвинутые трюки (по желанию) следующие изменения являются необязательными, но могут значительно сократить ваш код я считаю, что они уменьшают количество шаблонного кода вы, вероятно, заметили много ручных проверок параметров или аутентифицированного пользователя эти проверки гарантируют, что не произойдет странного поведения например, мы решили, что наш объект ‘post’ нуждается в тексте, поэтому, если параметр ‘text’ не передан, объект будет сохранен без него один из способов предотвратить это — проверить, был ли передан текст но ручные проверки могут быть времязатратными и неэстетичными в этом разделе мы воспользуемся деструктуризацией объектов для неявного выполнения этих проверок вы должны увидеть документацию выше, если не знаете, что такое деструктуризация но вкратце, это позволяет вам превратить свойство объекта в переменную с очень лаконичным синтаксисом 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 }); если это пугает, не переживайте полный код может помочь короче говоря, ‘assertparams’ — это утилита для выбрасывания ошибки, если значение неопределено мы можем проверять параметры одним движением, комбинируя деструктуризацию объектов и инициализацию объектов es2015 это убирает восемь или девять ручных проверок, которые начинают выглядеть неаккуратно через некоторое время 6 обновление на back4app после того как вы перенесли свой код, вам нужно сделать еще две вещи, чтобы он работал на back4app обновите версию вашего сервера back4app загрузите ваш новый облачный код я уже упоминал о первом шаге все, что вам нужно сделать, это войти в back4app и перейти на панель управления вашего приложения оттуда просто выберите "настройки сервера" слева, затем нажмите кнопку "настройки" на карточке "управление parse server" затем вы можете выбрать радиокнопку parse server 3 1 1 и нажать "сохранить" и последнее, но не менее важное, вы можете загрузить свой код через back4app cli https //blog back4app com/2017/01/20/cli parse server/ , или через вашу панель управления, используя ручную загрузку смотрите это руководство https //www back4app com/docs/android/parse cloud code если вам нужна дополнительная информация по этому шагу заметки по запуску новой версии если ваш код сложный, возможно, будет хорошей идеей провести некоторые тесты перед выполнением этих двух шагов back4app имеет несколько руководств о том, как это сделать здесь и здесь наконец, важно отметить, что эти изменения являются разрушительными использование кода, который мы написали на сервере parse 2 x, приведет к ошибке, и использование кода 2 x на сервере 3 1 также приведет к ошибке поэтому вы должны убедиться, что обновили вашу версию parse на back4app сразу после загрузки вашего обновленного cloud code если у вас много пользователей и вы беспокоитесь о том, что загрузка кода и обновление версии могут быть немного несинхронизированы, вы можете сделать что то вроде этого 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 functions на основе этого после загрузки этого кода вы измените версию на 3 1, а затем сможете повторно загрузить код, удалив старую часть включение проверки в начале гарантирует, что не будет момента, когда ваш код сломается поскольку вы можете обновить и загрузить в течение нескольких секунд, это обычно не требуется заключение в этом руководстве мы просто показали, как мигрировать ваш cloud code на релиз parse 3 1 не забудьте обновить вашу версию back4app до 3 1 после внесения этих изменений также важно отметить, что это руководство продемонстрировало улучшенный синтаксис, который использует parse 3 1 наши рефакторинги сократили кодовую базу с 160 строк до 90 и сделали ее гораздо более читаемой для реальных приложений это принесет дивиденды