Advanced Guides
Migrando para Parse Server 3.1: Guia de Cloud Code Async/Await
25 min
mais poder para seu app com parse server 3 1 introdução a comunidade parse lançou recentemente a versão 3 1 do parse server https //docs parseplatform org/parse server/guide/ esta atualização limpou a sintaxe do cloud code é muito mais adequada para aproveitar os construtos async e await do es6 além disso, algumas idiossincrasias associadas ao uso do parse foram eliminadas, por exemplo, as funções em nuvem simplesmente retornam uma promise em vez de usar as mensagens de erro erro ou sucesso sucesso no objeto response você pode atualizar seus aplicativos no back4app facilmente no seu painel este guia demonstrará como atualizar seu código para aproveitar os novos recursos do 3 1 para seguir este guia, você é bem vindo a dar uma olhada no projeto de exemplo fornecido este é um tutorial de convidado escrito por john considine https //github com/considine , desenvolvedor principal na k optional https //koptional com/ objetivos atualizar seu back4app parse server para 3 1 e migrar seu cloud code de acordo pré requisitos para completar este tutorial, você precisa ° um aplicativo back4app existente que esteja usando parse server 2 x ° siga o tutorial de criar novo app para aprender como criar um app no back4app resumo das mudanças as mudanças mais notáveis são as seguintes 1\ o cloud code funciona com parse sdk 2 x anteriormente, o cloud code funcionava com parse sdk 1 x com o parse server 3 1, ele funciona com parse sdk 2 x veja lançamentos do parse sdk para entender melhor o que isso implica este grande aumento de versão envolve principalmente correções de bugs também adiciona containedby e includeall métodos de consulta, bem como a capacidade de buscar um objeto com includes 2 atualização agregada desde o parse 2 7 1, você pode usar o método aggregate em uma consulta isso permite que você aproveite um pouco mais o banco de dados subjacente agora, a sintaxe para o método aggregate em parse query parse query foi atualizada você pode executar uma consulta usando duas etapas a match match e a group group etapa anteriormente, você não precisava da chave pipeline no objeto pipeline devido à api subjacente, agora você deve incluir explicitamente a chave pipeline o valor deve ser um array de um ou dois estágios, apresentando group group e match match veja documentação oficial do parse para exemplos mais específicos 3 otimizações internas algumas otimizações internas foram feitas por exemplo, um parse livequery buscará permissões de nível de classe (clps) junto com os dados para evitar acesso duplo ao banco de dados 4\ email de redefinição do parse ao solicitar um e mail de redefinição de senha, o servidor retornará sucesso mesmo que esse e mail não esteja salvo além disso, os tokens de redefinição de senha expiram quando o e mail de um usuário é redefinido 5\ atualização de gatilhos em nuvem com este lançamento, você pode compartilhar dados entre os beforesave e aftersave gatilhos no mesmo objeto por exemplo 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 }); você pode ver mais sobre as mudanças no parse server no changelog oficial do parse 3 1 clicando aqui 6\ melhoria do livequery o cliente parse livequery permite que você se inscreva em consultas e receba atualizações do servidor à medida que elas chegam consultas tradicionais são executadas uma vez pelo cliente, então isso é muito útil para casos como mensagens, etc com o back4app você também pode aproveitar esta tecnologia https //www back4app com/docs/platform/parse server live query example com o lançamento da versão 3 x, a comunidade parse melhorou o sistema para livequery acls https //docs parseplatform org/js/guide/#security for other objects agora você pode passar um token de sessão para o método subscribe de uma live query, e o parse server gerenciará apenas a devolução de resultados aos quais este usuário tem acesso por exemplo, um usuário pode ter acesso de leitura/gravação a certas ‘mensagens’, mas não a todas 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); o código acima irá automaticamente se inscrever em todas as mensagens às quais o usuário tem acesso, aliviando você da responsabilidade de consultar mensagens específicas a parte principal das mudanças diz respeito a como o cloud code é tratado para isso, veja o guia de migração abaixo 1 alinhando fundamentos técnicos começaremos com um exemplo de projeto em nuvem usando a versão 2 x assim, podemos navegar pelas mudanças apropriadas de sintaxe você pode ver o repositório para este projeto de exemplo se você está familiarizado com async e await, pode pular esta seção a evolução do código assíncrono em javascript se parece com isto funções de callback promessas async / await qualquer aplicação moderna em javascript provavelmente usará os três funções de callback envolvem passar uma função como argumento para outra função esta segunda função pode executar a primeira em algum momento 1 // callbacks 2 // executes callback function after waiting 100 milliseconds 3 settimeout(function() { 4 alert('my callback function'); 5 }, 100); os callbacks são essenciais, mas podem ser complicados quando se trata de encadear muitos deles especificamente, aninhar várias camadas pode ser difícil de ler, e o tratamento de erros se torna complicado portanto, no es2015, a promise foi introduzida 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)); as promessas melhoram a legibilidade da programação assíncrona elas também tornam os pipelines mais explícitos mas avanços ainda maiores foram feitos em es2017 com os construtos async / await seu código agora pode esperar pelos resultados de uma promise sem depender dos blocos then / catch (que também podem se tornar difíceis de ler) 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 } talvez, para um exemplo muito simples, isso pode não parecer mais elegante do que promessas simples mas aguardar os resultados de uma função assíncrona é frequentemente exatamente o que queremos fazer portanto, isso realmente otimiza a legibilidade do nosso código suporte para async/await como mencionado anteriormente, async/await foi incluído na especificação ecmascript 2017 (es8) para código de servidor, versionamento raramente é um problema, uma vez que você pode atualizar para a versão do node js que suporta esses recursos fique tranquilo, o ambiente do back4app suporta versões estáveis recentes para código de navegador, transpiladores como babel produzirão um es2016 compatível com código que usa async / await e funciona em navegadores modernos 2 pensando sobre seu código de forma diferente a principal mudança com o cloud code envolve o que o desenvolvedor faz em comparação com o que a biblioteca faz anteriormente, você gerenciava explicitamente a resposta como a maioria do cloud code será executada de forma assíncrona fazendo consultas e gravações no banco de dados faz mais sentido retornar uma promise, reduzindo o código boilerplate a intuição por trás das funções cloud é que há uma configuração e configuração mínimas envolvidas na escrita de código do lado do servidor este lançamento incorpora essa ideia; tenha isso em mente enquanto você refatora e cria novas funções para mostrar como as funções cloud code funcionam no parse server 3 1, reescrevemos um exemplo funcional de cloud code de uma versão do parse server antes da migração você pode encontrar este código clicando aqui a mesma função cloud code é escrita no parse 3 1, conforme mostrado abaixo 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 adicionando todos os marcadores async qualquer função que usa await deve ser declarada com o modificador async esta simples refatoração irá anexar async a todas as cloud functions também irá substituí las por funções de seta pois são mais sucintas neste caso (e é o que o guia oficial atualizado do parse utiliza) 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 } seu código ficará assim isto após esta refatoração nada de louco até agora no próximo passo, vamos obter o que vale a pena por essa mudança 4 removendo referências à resposta, empregue await seu código ficará assim isto após essa refatoração este passo é um pouco mais complicado precisamos remover todas as referências à variável ‘response’, retornando uma promessa em vez disso no caso de múltiplas funções de consulta/salvamento, aguarde a resposta confira o método de criação de comentários para ver como isso é feito 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 }); observe que agora um erro javascript é lançado em vez de chamar response error o parse lidará com a transformação disso em uma resposta para nós excluir um ‘post’ ou ‘comentário’ envolve primeiro pegar o objeto e depois destruí lo ao usar ‘await’, o método de destruição pode acessar o objeto salvo fora de um bloco isso completa toda a refatoração necessária para a migração ou seja, se você chegar até este passo, parabéns! seu código funcionará no back4app parse 3 1! 5 truques avançados (opcional) as seguintes mudanças são opcionais, mas podem encurtar significativamente seu código eu acho que elas reduzem o boilerplate você provavelmente notou muitas verificações manuais para parâmetros ou para o usuário autenticado essas garantem que comportamentos estranhos não ocorram por exemplo, decidimos que nosso objeto ‘post’ precisa de texto, então se nenhum parâmetro ‘text’ for passado, o objeto será salvo sem ele uma maneira de evitar isso é verificar se o texto foi passado mas verificações manuais podem ser demoradas e inelegantes nesta seção, aproveitamos desestruturação de objetos para completar implicitamente essas verificações você deve ver a documentação acima se não souber o que é desestruturação mas, em resumo, ela permite que você transforme a propriedade de um objeto em uma variável com uma sintaxe muito concisa 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 a desestruturação é menos verbosa do que a atribuição manual também permite que você declare variáveis de parâmetro rapidamente, o que é bom 1 parse cloud define('posts\ get', async ({ params { id } }) => { 2 // id is declared 3 }); quando combinado com uma notação es2015 para inicialização de objeto podemos otimizar nossas verificações de parâmetro podemos fazer isso 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 então, para o nosso código parse, podemos fazer isso 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 }); se isso é assustador, não se preocupe o código completo pode ajudar em resumo, ‘assertparams’ é uma função utilitária para lançar um erro se um valor estiver indefinido podemos verificar os parâmetros em um único movimento combinando a desestruturação de objetos e a inicialização de objetos do es2015 isso remove oito ou nove verificações manuais que começam a se tornar desagradáveis após um tempo 6 atualizando no back4app uma vez que você tenha migrado seu código, deve fazer mais duas coisas para que ele funcione no back4app atualize a versão do seu servidor back4app carregue seu novo código em nuvem eu mencionei brevemente o primeiro passo antes tudo o que você precisa fazer é fazer login no back4app e ir para o painel do seu aplicativo a partir daí, basta selecionar “configurações do servidor” à esquerda, seguido pelo botão “configurações” no cartão “gerenciar parse server” você pode então selecionar o botão de opção do parse server 3 1 1 e clicar em “salvar” por último, mas não menos importante, você pode carregar seu código via back4app cli https //blog back4app com/2017/01/20/cli parse server/ , ou pelo seu painel usando o upload manual veja este guia https //www back4app com/docs/android/parse cloud code se você precisar de mais informações sobre este passo notas sobre o lançamento de uma nova versão se o seu código for complexo, pode ser uma boa ideia executar alguns testes antes de realizar esses dois passos o back4app tem alguns guias sobre como fazer isso aqui e aqui finalmente, é importante notar que essas mudanças são breaking usar o código que escrevemos em um parse server 2 x falhará, e usar código 2 x em um servidor 3 1 também falhará portanto, você deve garantir que atualize sua versão do back4app assim que fizer o upload do seu cloud code atualizado se você tiver muitos usuários e estiver preocupado com o upload do código e a atualização da versão estarem ligeiramente fora de sincronia, você pode fazer algo assim 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 } este código descobre dinamicamente a versão e define funções em nuvem com base nisso após fazer o upload disso, você mudaria para 3 1 e, em seguida, poderia re enviar o código com a parte antiga removida incluir a verificação no início garante que não haja um ponto em que seu código falhe como você pode atualizar e fazer o upload em poucos segundos, geralmente não é necessário conclusão neste guia, demonstramos simplesmente como migrar seu cloud code para a versão parse 3 1 lembre se de atualizar sua versão do back4app para 3 1 após fazer essas mudanças além disso, este guia demonstrou uma sintaxe aprimorada que o parse 3 1 utiliza nossas refatorações reduziram a base de código de 160 linhas para 90 e tornaram na muito mais legível para aplicações reais, isso trará dividendos