{"id":1616,"date":"2014-12-16T19:32:08","date_gmt":"2014-12-16T19:32:07","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1616"},"modified":"2023-06-28T00:23:43","modified_gmt":"2023-06-28T07:23:43","slug":"game-servers-and-couchbase-nodejs-part-3","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-3\/","title":{"rendered":"Servidores de jogos e Couchbase com Node.js - Parte 3"},"content":{"rendered":"<p>Nesta parte da s\u00e9rie, configuraremos um sistema de armazenamento de dados do jogo para permitir que voc\u00ea armazene o estado do jogo do jogador ao longo de sua experi\u00eancia com o jogo. Para isso, criaremos alguns pontos de extremidade \/state e \/states que representar\u00e3o blocos individuais de dados de estado. Permitiremos v\u00e1rios blocos de estado nomeados para permitir que o jogo divida os dados de estado em blocos atualiz\u00e1veis separadamente para evitar a necessidade de gravar muitos blocos de estado quando apenas uma parte tiver sido alterada.<\/p>\n<p>Se voc\u00ea ainda n\u00e3o leu <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-1\/\">Parte 1<\/a> e <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-2\/\">Parte 2<\/a> desta s\u00e9rie, sugiro que voc\u00ea o fa\u00e7a, pois esta parte e as futuras se baseiam nelas!<\/p>\n<h1>Ajuda r\u00e1pida - Renova\u00e7\u00e3o da sess\u00e3o<\/h1>\n<p>Algo que deveria estar na minha postagem anterior do blog, mas que \u00e9 importante, \u00e9 a renova\u00e7\u00e3o da sess\u00e3o dos usu\u00e1rios sempre que eles a acessam. Sem isso, \u00e9 garantido que a sess\u00e3o expire ap\u00f3s 60 minutos, independentemente de o jogador ainda estar jogando. Obviamente, essa n\u00e3o \u00e9 a nossa inten\u00e7\u00e3o, portanto, vamos corrigir isso!<\/p>\n<p>Primeiro, precisamos adicionar uma nova fun\u00e7\u00e3o ao nosso SessionModel, portanto, abra o arquivo sessionmodel.js e vamos adicionar o seguinte bloco. \u00c9 uma fun\u00e7\u00e3o bastante simples; ela recebe um ID de sess\u00e3o e executa uma opera\u00e7\u00e3o de toque para redefinir o tempo de expira\u00e7\u00e3o para 3600 novamente (a partir do momento da execu\u00e7\u00e3o do toque, n\u00e3o quando a chave foi originalmente inserida).<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>SessionModel.<span style=\"color: #660066\">toque<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>lado<span style=\"color: #339933\">,<\/span> retorno de chamada<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> sessDocName <span style=\"color: #339933\">=<\/span> <span style=\"color: #3366cc\">'sess-'<\/span> <span style=\"color: #339933\">+<\/span> lado<span style=\"color: #339933\">;<\/span><\/p>\n<p>db.<span style=\"color: #660066\">toque<\/span><span style=\"color: #009900\">(<\/span>sessDocName<span style=\"color: #339933\">,<\/span> <span style=\"color: #009900\">{<\/span>expira\u00e7\u00e3o<span style=\"color: #339933\">:<\/span> <span style=\"color: #cc0000\">3600<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nretorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>Agora que temos nossa fun\u00e7\u00e3o de modelo para atualizar a sess\u00e3o, vamos encontrar um bom lugar para cham\u00e1-la. Nosso m\u00e9todo authUser parece ser uma boa op\u00e7\u00e3o, pois \u00e9 executado em qualquer endpoint que exija que o usu\u00e1rio seja autenticado. Vamos fazer isso agora. Aqui est\u00e1 nossa nova fun\u00e7\u00e3o authUser com nossa chamada de toque adicionada.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span> authUser<span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span> res<span style=\"color: #339933\">,<\/span> pr\u00f3xima<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nreq.<span style=\"color: #660066\">uid<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">cabe\u00e7alhos<\/span>.<span style=\"color: #660066\">autoriza\u00e7\u00e3o<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> authInfo <span style=\"color: #339933\">=<\/span> req.<span style=\"color: #660066\">cabe\u00e7alhos<\/span>.<span style=\"color: #660066\">autoriza\u00e7\u00e3o<\/span>.<span style=\"color: #660066\">dividir<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">&#8216; &#8216;<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>authInfo<span style=\"color: #009900\">[<\/span><span style=\"color: #cc0000\">0<\/span><span style=\"color: #009900\">]<\/span> <span style=\"color: #339933\">===<\/span> <span style=\"color: #3366cc\">\"Portador<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> lado <span style=\"color: #339933\">=<\/span> authInfo<span style=\"color: #009900\">[<\/span><span style=\"color: #cc0000\">1<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #339933\">;<\/span><br \/>\nsessionModel.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>lado<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> uid<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\npr\u00f3xima<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'Seu ID de sess\u00e3o \u00e9 inv\u00e1lido'<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nsessionModel.<span style=\"color: #660066\">toque<\/span><span style=\"color: #009900\">(<\/span>lado<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\nreq.<span style=\"color: #660066\">uid<\/span> <span style=\"color: #339933\">=<\/span> uid<span style=\"color: #339933\">;<\/span><br \/>\npr\u00f3xima<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\npr\u00f3xima<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'Deve ser autorizado a acessar esse endpoint'<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\npr\u00f3xima<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'Deve ser autorizado a acessar esse endpoint'<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Como parte dessa corre\u00e7\u00e3o de expira\u00e7\u00e3o de sess\u00e3o, talvez seja necess\u00e1rio extrair a vers\u00e3o do couchnode diretamente do GitHub devido a um erro em nossa implementa\u00e7\u00e3o de toque que foi corrigido antes da publica\u00e7\u00e3o deste blog, mas ap\u00f3s o lan\u00e7amento do ciclo mais recente.<\/p>\n<h1>Estados do jogo - O modelo<\/h1>\n<p>Agora que j\u00e1 resolvemos o pequeno problema da parte anterior, vamos implementar o salvamento do estado do jogo! Como eu disse acima, vamos permitir que os jogos armazenem dados em v\u00e1rios blocos de estado para reduzir o tr\u00e1fego de rede. Do ponto de vista do armazenamento, armazenaremos todos esses blocos de estado em um \u00fanico documento do Couchbase, e esse documento ser\u00e1 criado de forma pregui\u00e7osa na primeira solicita\u00e7\u00e3o para salvar informa\u00e7\u00f5es para o usu\u00e1rio. At\u00e9 o momento em que houver algo salvo, emularemos uma lista de estados vazia para o usu\u00e1rio, como voc\u00ea ver\u00e1 em breve.<\/p>\n<p>Para come\u00e7ar, vamos configurar nosso layout de arquivo de modelo padr\u00e3o em model\/statemodel.js. Importamos nossos m\u00f3dulos necess\u00e1rios e configuramos um modelo sem m\u00e9todos chamado StateModel.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p><span style=\"color: #003366;font-weight: bold\">var<\/span> db <span style=\"color: #339933\">=<\/span> exigir<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'.\/..\/database'<\/span><span style=\"color: #009900\">)<\/span>.<span style=\"color: #660066\">mainBucket<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> couchbase <span style=\"color: #339933\">=<\/span> exigir<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'couchbase'<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<p><span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span> Modelo de Estado<span style=\"color: #009900\">(<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>m\u00f3dulo.<span style=\"color: #660066\">exporta\u00e7\u00f5es<\/span> <span style=\"color: #339933\">=<\/span> Modelo de Estado<span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>Agora que temos os fundamentos do nosso modelo, vamos come\u00e7ar a implementar alguns dos m\u00e9todos que ser\u00e3o necess\u00e1rios. Vamos come\u00e7ar com um modelo que nos permita salvar um novo bloco de estado. Essa fun\u00e7\u00e3o tratar\u00e1 tanto da cria\u00e7\u00e3o quanto da atualiza\u00e7\u00e3o de um bloco de estado. Isso torna a l\u00f3gica do lado do cliente muito mais simples, pois n\u00e3o precisamos nos preocupar se o bloco de estado j\u00e1 existe em um n\u00edvel de API. Usaremos uma forma de bloqueio otimista em que um n\u00famero de vers\u00e3o ser\u00e1 armazenado com cada bloco de estado. Sempre que um bloco de estado for atualizado, voc\u00ea precisar\u00e1 passar o n\u00famero da vers\u00e3o existente no servidor antes que o servidor aceite os novos dados. Isso serve para evitar que v\u00e1rias c\u00f3pias do jogo em execu\u00e7\u00e3o simult\u00e2nea atropelem os dados umas das outras. Esse tamb\u00e9m \u00e9 o primeiro lugar em que usaremos a fun\u00e7\u00e3o <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/optimistic-or-pessimistic-locking-which-one-should-you-pick\/\">bloqueio otimista<\/a> para garantir que n\u00e3o estejamos fazendo altera\u00e7\u00f5es simult\u00e2neas em nosso objeto de estados a partir de duas chamadas de endpoint.<\/p>\n<p>Vamos come\u00e7ar com nosso prot\u00f3tipo de fun\u00e7\u00e3o de salvamento.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">StateModel.<span style=\"color: #660066\">salvar<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>uid<span style=\"color: #339933\">,<\/span> <span style=\"color: #000066\">nome<\/span><span style=\"color: #339933\">,<\/span> preVer<span style=\"color: #339933\">,<\/span> dados<span style=\"color: #339933\">,<\/span> retorno de chamada<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><\/div>\n<\/div>\n<p>Nossa primeira etapa real \u00e9 criar um nome para o nosso documento de armazenamento de estado e, em seguida, solicitar esse documento ao Couchbase para verificar se ele j\u00e1 existe.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">var<\/span> stateDocName <span style=\"color: #339933\">=<\/span> <span style=\"color: #3366cc\">'usu\u00e1rio-'<\/span> <span style=\"color: #339933\">+<\/span> uid <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">'-estado'<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndb.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #006600;font-style: italic\">\/\/ O c\u00f3digo abaixo vai para c\u00e1!<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/div>\n<\/div>\n<p>Agora, verificamos se houve algum erro ao solicitar um documento de estado existente. Se encontrarmos um erro, verificaremos se n\u00e3o foi um erro \"n\u00e3o encontrado\". Se o documento n\u00e3o foi encontrado, ignoramos esse erro e continuamos, pois isso se deve \u00e0 natureza de cria\u00e7\u00e3o pregui\u00e7osa do nosso documento de estados.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>err.<span style=\"color: #660066\">c\u00f3digo<\/span> <span style=\"color: #339933\">!==<\/span> couchbase.<span style=\"color: #660066\">erros<\/span>.<span style=\"color: #660066\">keyNotFound<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Em seguida, movemos nosso documento de estado existente (ou um novo documento, caso n\u00e3o tenha sido encontrado) para uma vari\u00e1vel separada para facilitar o acesso e para que possamos lidar com os documentos existentes e com o novo documento da mesma maneira.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">var<\/span> documento de estado <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ntipo<span style=\"color: #339933\">:<\/span> <span style=\"color: #3366cc\">\"estado<\/span><span style=\"color: #339933\">,<\/span><br \/>\nuid<span style=\"color: #339933\">:<\/span> uid<span style=\"color: #339933\">,<\/span><br \/>\nestados<span style=\"color: #339933\">:<\/span> <span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ndocumento de estado <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Agora, faremos a mesma coisa com nosso bloco de estado. Voc\u00ea notar\u00e1 que garantimos que nossa vari\u00e1vel stateBlock fa\u00e7a refer\u00eancia \u00e0 matriz de estados dos documentos de estado reais. Outro ponto que vale a pena mencionar \u00e9 que nossa vers\u00e3o padr\u00e3o do bloco de estado \u00e9 0. Isso significa que, ao executar um salvamento pela primeira vez, espera-se que o cliente especifique a vers\u00e3o 0 para esclarecer que est\u00e1 ciente de que esse ser\u00e1 um novo bloco de estado.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">var<\/span> stateBlock <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nvers\u00e3o<span style=\"color: #339933\">:<\/span> <span style=\"color: #cc0000\">0<\/span><span style=\"color: #339933\">,<\/span><br \/>\ndados<span style=\"color: #339933\">:<\/span> <span style=\"color: #003366;font-weight: bold\">nulo<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateBlock <span style=\"color: #339933\">=<\/span> stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span> <span style=\"color: #339933\">=<\/span> stateBlock<span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Em seguida, precisamos verificar se a vers\u00e3o especificada pelo chamador ainda corresponde \u00e0 que est\u00e1 armazenada em nosso cluster. Se esse n\u00e3o for o caso, outro usu\u00e1rio deve ter feito altera\u00e7\u00f5es desde a \u00faltima vez em que o cliente recuperou os dados salvos. Espera-se que, se houver uma incompatibilidade de vers\u00e3o, o cliente recupere os novos dados, fa\u00e7a as mesclagens necess\u00e1rias e tente atualizar novamente.<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace\">Se (stateBlock.version !== preVer) {<br \/>\nreturn callback('Sua vers\u00e3o n\u00e3o corresponde \u00e0 vers\u00e3o do servidor.');<br \/>\n} else {<br \/>\nstateBlock.version++;<br \/>\nstateBlock.data = data;<br \/>\n}<\/div>\n<\/div>\n<p>Como mencionei no in\u00edcio desta se\u00e7\u00e3o, tamb\u00e9m usaremos o bloqueio otimista incorporado ao Couchbase para garantir que nossas grava\u00e7\u00f5es de documentos de estado sejam executadas em ordem. Devido ao fato de que realizamos nosso get anteriormente, depois fazemos nossa compara\u00e7\u00e3o de vers\u00f5es e, finalmente, fazemos a grava\u00e7\u00e3o novamente aqui, h\u00e1 uma chance de que outra chamada ao nosso endpoint de salvamento de estado tenha alterado o objeto desde o nosso get original, mas antes do nosso set. Para saber mais sobre os valores cas, consulte a se\u00e7\u00e3o <a href=\"https:\/\/docs.couchbase.com\/couchbase-devguide-2.2\/#check-and-set-cas\">Manual do Couchbase sobre valores cas<\/a>.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">var<\/span> setOptions <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nsetOptions.<span style=\"color: #660066\">cas<\/span> <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">cas<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/div>\n<\/div>\n<p>Por \u00faltimo, para esse m\u00e9todo espec\u00edfico, pr\u00e9-formamos nosso conjunto, todos os erros que ocorrem s\u00e3o propagados para o chamador (isso provavelmente deve ser envolvido no n\u00edvel do modelo, conforme mencionado anteriormente) e o retorno de chamada \u00e9 invocado com o bloco de estado que armazenamos.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>db.<span style=\"color: #660066\">definir<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> documento de estado<span style=\"color: #339933\">,<\/span> setOptions<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">,<\/span> stateBlock<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>Por fim, aqui est\u00e1 todo o nosso m\u00e9todo de salvamento. Ele \u00e9 bastante longo, mas espero que seja relativamente compreens\u00edvel!<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>StateModel.<span style=\"color: #660066\">salvar<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>uid<span style=\"color: #339933\">,<\/span> <span style=\"color: #000066\">nome<\/span><span style=\"color: #339933\">,<\/span> preVer<span style=\"color: #339933\">,<\/span> dados<span style=\"color: #339933\">,<\/span> retorno de chamada<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> stateDocName <span style=\"color: #339933\">=<\/span> <span style=\"color: #3366cc\">'usu\u00e1rio-'<\/span> <span style=\"color: #339933\">+<\/span> uid <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">'-estado'<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndb.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>err.<span style=\"color: #660066\">c\u00f3digo<\/span> <span style=\"color: #339933\">!==<\/span> couchbase.<span style=\"color: #660066\">erros<\/span>.<span style=\"color: #660066\">keyNotFound<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p><span style=\"color: #003366;font-weight: bold\">var<\/span> documento de estado <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ntipo<span style=\"color: #339933\">:<\/span> <span style=\"color: #3366cc\">\"estado<\/span><span style=\"color: #339933\">,<\/span><br \/>\nuid<span style=\"color: #339933\">:<\/span> uid<span style=\"color: #339933\">,<\/span><br \/>\nestados<span style=\"color: #339933\">:<\/span> <span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\ndocumento de estado <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p><span style=\"color: #003366;font-weight: bold\">var<\/span> stateBlock <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nvers\u00e3o<span style=\"color: #339933\">:<\/span> <span style=\"color: #cc0000\">0<\/span><span style=\"color: #339933\">,<\/span><br \/>\ndados<span style=\"color: #339933\">:<\/span> <span style=\"color: #003366;font-weight: bold\">nulo<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateBlock <span style=\"color: #339933\">=<\/span> stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span> <span style=\"color: #339933\">=<\/span> stateBlock<span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p><span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>stateBlock.<span style=\"color: #660066\">vers\u00e3o<\/span> <span style=\"color: #339933\">!==<\/span> preVer<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'Sua vers\u00e3o n\u00e3o corresponde \u00e0 vers\u00e3o do servidor'.<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateBlock.<span style=\"color: #660066\">vers\u00e3o<\/span><span style=\"color: #339933\">++;<\/span><br \/>\nstateBlock.<span style=\"color: #660066\">dados<\/span> <span style=\"color: #339933\">=<\/span> dados<span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p><span style=\"color: #003366;font-weight: bold\">var<\/span> setOptions <span style=\"color: #339933\">=<\/span> <span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nsetOptions.<span style=\"color: #660066\">cas<\/span> <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">cas<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>db.<span style=\"color: #660066\">definir<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> documento de estado<span style=\"color: #339933\">,<\/span> setOptions<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">,<\/span> stateBlock<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>O pr\u00f3ximo m\u00e9todo que incluiremos \u00e9 o findByUserId. Esse m\u00e9todo nos permitir\u00e1 criar um ponto de extremidade que retorne todos os blocos de estado para qualquer usu\u00e1rio espec\u00edfico. Trata-se principalmente de uma otimiza\u00e7\u00e3o no lado do cliente para permitir a busca de todos os blocos de estado de uma s\u00f3 vez, em vez de executar v\u00e1rias solicita\u00e7\u00f5es. A fun\u00e7\u00e3o \u00e9 extremamente simples. Usando o mesmo nome de documento da nossa fun\u00e7\u00e3o de salvamento, tentamos carregar o documento de estado do nosso cluster; se ele existir, retornamos a lista de estados dentro desse bloco; se o documento estiver ausente, retornamos uma lista vazia para o usu\u00e1rio. Quaisquer outros erros s\u00e3o encaminhados para o chamador.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>StateModel.<span style=\"color: #660066\">findByUserId<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>uid<span style=\"color: #339933\">,<\/span> retorno de chamada<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> stateDocName <span style=\"color: #339933\">=<\/span> <span style=\"color: #3366cc\">'usu\u00e1rio-'<\/span> <span style=\"color: #339933\">+<\/span> uid <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">'-estado'<\/span><span style=\"color: #339933\">;<\/span><br \/>\ndb.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>err.<span style=\"color: #660066\">c\u00f3digo<\/span> <span style=\"color: #339933\">===<\/span> couchbase.<span style=\"color: #660066\">erros<\/span>.<span style=\"color: #660066\">keyNotFound<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #009900\">{<\/span><span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span> <span style=\"color: #000066;font-weight: bold\">mais<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> documento de estado <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<p>retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">,<\/span> stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>A \u00faltima fun\u00e7\u00e3o de modelo que precisamos criar \u00e9 o nosso m\u00e9todo para acessar um \u00fanico bloco de estado para um usu\u00e1rio. Essa fun\u00e7\u00e3o \u00e9 quase id\u00eantica \u00e0 nossa fun\u00e7\u00e3o findByUserId, exceto pelo fato de que, al\u00e9m disso, detalhamos um bloco de estado espec\u00edfico por nome em vez de retornar a lista inteira.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>StateModel.<span style=\"color: #660066\">obter<\/span> <span style=\"color: #339933\">=<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>uid<span style=\"color: #339933\">,<\/span> <span style=\"color: #000066\">nome<\/span><span style=\"color: #339933\">,<\/span> retorno de chamada<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> stateDocName <span style=\"color: #339933\">=<\/span> <span style=\"color: #3366cc\">'usu\u00e1rio-'<\/span> <span style=\"color: #339933\">+<\/span> uid <span style=\"color: #339933\">+<\/span> <span style=\"color: #3366cc\">'-estado'<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<p>db.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>stateDocName<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> resultado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><br \/>\n<span style=\"color: #003366;font-weight: bold\">var<\/span> documento de estado <span style=\"color: #339933\">=<\/span> resultado.<span style=\"color: #660066\">valor<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<p><span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span><span style=\"color: #339933\">!<\/span>stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'N\u00e3o existe nenhum bloco de estado com esse nome'.<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>retorno de chamada<span style=\"color: #009900\">(<\/span><span style=\"color: #003366;font-weight: bold\">nulo<\/span><span style=\"color: #339933\">,<\/span> stateDoc.<span style=\"color: #660066\">estados<\/span><span style=\"color: #009900\">[<\/span><span style=\"color: #000066\">nome<\/span><span style=\"color: #009900\">]<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<h1>Estados do jogo - Tratamento de solicita\u00e7\u00f5es<\/h1>\n<p>Agora que temos nosso modelo pronto para ser usado, vamos come\u00e7ar a criar os manipuladores de solicita\u00e7\u00e3o para nossos tr\u00eas pontos de extremidade! Vamos criar um ponto de extremidade para solicitar todos os estados de um usu\u00e1rio, um ponto de extremidade para solicitar um bloco de estado espec\u00edfico e, finalmente, um ponto de extremidade para atualizar um bloco de estado espec\u00edfico.<\/p>\n<p>Antes de criarmos nossos manipuladores de solicita\u00e7\u00f5es, precisamos primeiro adicionar uma refer\u00eancia ao arquivo statemodel.js que criamos anteriormente!<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\"><span style=\"color: #003366;font-weight: bold\">var<\/span> modelo de estado <span style=\"color: #339933\">=<\/span> exigir<span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'.\/models\/statemodel'<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/div>\n<\/div>\n<p>Agora, vamos come\u00e7ar com nosso endpoint de salvamento. Como nas partes anteriores, nossos manipuladores de solicita\u00e7\u00e3o s\u00e3o extremamente simples e simplesmente encaminham as partes pertinentes da nossa solicita\u00e7\u00e3o para o modelo. Esperamos o nome do bloco de estado como parte do URI, o n\u00famero da vers\u00e3o como parte da nossa consulta e, finalmente, os dados reais do bloco de estado no corpo da solicita\u00e7\u00e3o.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>aplicativo.<span style=\"color: #660066\">colocar<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'\/estado\/:nome'<\/span><span style=\"color: #339933\">,<\/span> authUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span> res<span style=\"color: #339933\">,<\/span> pr\u00f3xima<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateModel.<span style=\"color: #660066\">salvar<\/span><span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">uid<\/span><span style=\"color: #339933\">,<\/span> req.<span style=\"color: #660066\">par\u00e2metros<\/span>.<span style=\"color: #000066\">nome<\/span><span style=\"color: #339933\">,<\/span> parseInt<span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">consulta<\/span>.<span style=\"color: #660066\">preVer<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #cc0000\">10<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">,<\/span><br \/>\nreq.<span style=\"color: #660066\">corpo<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> estado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> pr\u00f3xima<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>res.<span style=\"color: #660066\">enviar<\/span><span style=\"color: #009900\">(<\/span>estado<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>Em seguida, precisamos da capacidade de recuperar um bloco de estado que armazenamos anteriormente.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>aplicativo.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'\/estado\/:nome'<\/span><span style=\"color: #339933\">,<\/span> authUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span> res<span style=\"color: #339933\">,<\/span> pr\u00f3xima<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateModel.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">uid<\/span><span style=\"color: #339933\">,<\/span> req.<span style=\"color: #660066\">par\u00e2metros<\/span>.<span style=\"color: #000066\">nome<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> estado<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> pr\u00f3xima<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>res.<span style=\"color: #660066\">enviar<\/span><span style=\"color: #009900\">(<\/span>estado<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<p>Por \u00faltimo, mas n\u00e3o menos importante, o ponto de extremidade para solicitar todos os blocos de estado armazenados para um determinado usu\u00e1rio. Como eu disse antes, isso serve principalmente para otimizar a sequ\u00eancia de carregamento do jogo, em que geralmente precisamos recuperar todos os blocos de estado.<\/p>\n<div class=\"geshifilter\">\n<div class=\"javascript geshifilter-javascript\" style=\"font-family: monospace\">\n<p>aplicativo.<span style=\"color: #660066\">obter<\/span><span style=\"color: #009900\">(<\/span><span style=\"color: #3366cc\">'\/estados'<\/span><span style=\"color: #339933\">,<\/span> authUser<span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>req<span style=\"color: #339933\">,<\/span> res<span style=\"color: #339933\">,<\/span> pr\u00f3xima<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\nstateModel.<span style=\"color: #660066\">findByUserId<\/span><span style=\"color: #009900\">(<\/span>req.<span style=\"color: #660066\">uid<\/span><span style=\"color: #339933\">,<\/span> <span style=\"color: #003366;font-weight: bold\">fun\u00e7\u00e3o<\/span><span style=\"color: #009900\">(<\/span>erro<span style=\"color: #339933\">,<\/span> estados<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">se<\/span> <span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span> <span style=\"color: #009900\">{<\/span><br \/>\n<span style=\"color: #000066;font-weight: bold\">retorno<\/span> pr\u00f3xima<span style=\"color: #009900\">(<\/span>erro<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><\/p>\n<p>res.<span style=\"color: #660066\">enviar<\/span><span style=\"color: #009900\">(<\/span>estados<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/>\n<span style=\"color: #009900\">}<\/span><span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><\/p>\n<\/div>\n<\/div>\n<h1>Terminou!<\/h1>\n<p>Agora que criamos nosso modelo e implementamos os manipuladores de solicita\u00e7\u00e3o necess\u00e1rios, voc\u00ea poder\u00e1 iniciar o aplicativo como nas partes anteriores e executar algumas solicita\u00e7\u00f5es no servidor do jogo para ver o resultado do nosso trabalho \u00e1rduo!<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace\">\n<p>&gt; POST \/state\/test?preVer=0<br \/>\nCabe\u00e7alho (Autoriza\u00e7\u00e3o): Bearer 0e9dd36c-5e2c-4f0e-9c2c-bffeea72d4f7<br \/>\n{<br \/>\n\"name\": \"We Rock!\",<br \/>\n\"N\u00edvel\": \"13\"<br \/>\n}<br \/>\n&lt; 200 OK<br \/>\n{<br \/>\n\"vers\u00e3o\": 1,<br \/>\n\"data\": {<br \/>\n\"name\": \"We Rock!\",<br \/>\n\"N\u00edvel\": \"13\"<br \/>\n}<br \/>\n}<\/p>\n<p>&gt; GET \/estado\/teste<br \/>\nCabe\u00e7alho (Autoriza\u00e7\u00e3o): Bearer 0e9dd36c-5e2c-4f0e-9c2c-bffeea72d4f7<br \/>\n&lt; 200 OK<br \/>\n{<br \/>\n\"vers\u00e3o\": 1,<br \/>\n\"data\": {<br \/>\n\"name\": \"We Rock!\",<br \/>\n\"N\u00edvel\": \"13\"<br \/>\n}<br \/>\n}<\/p>\n<p>&gt; GET \/states<br \/>\nCabe\u00e7alho (Autoriza\u00e7\u00e3o): Bearer 0e9dd36c-5e2c-4f0e-9c2c-bffeea72d4f7<br \/>\n&lt; 200 OK<br \/>\n{<br \/>\n\"teste\": {<br \/>\n\"vers\u00e3o\": 1,<br \/>\n\"data\": {<br \/>\n\"name\": \"We Rock!\",<br \/>\n\"N\u00edvel\": \"13\"<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<\/div>\n<\/div>\n<p><b>Sucesso!<\/b><\/p>\n<p>A fonte completa desse aplicativo est\u00e1 dispon\u00edvel aqui: <a href=\"https:\/\/github.com\/brett19\/node-gameapi\">https:\/\/github.com\/brett19\/node-gameapi<\/a><\/p>\n<p>Aproveite! Brett<\/p>","protected":false},"excerpt":{"rendered":"<p>In this part of the series, we will be setting up a game data storage system to allow you to store player game state over the course of their enjoyment of your game. To do this, we are going to [&hellip;]<\/p>","protected":false},"author":31,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[9004],"class_list":["post-1616","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Game Servers and Couchbase with Node.js - Part 3 - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-3\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Game Servers and Couchbase with Node.js - Part 3\" \/>\n<meta property=\"og:description\" content=\"In this part of the series, we will be setting up a game data storage system to allow you to store player game state over the course of their enjoyment of your game. To do this, we are going to [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-3\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-16T19:32:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-28T07:23:43+00:00\" \/>\n<meta name=\"author\" content=\"Brett Lawson, Principal Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Brett Lawson, Principal Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/\"},\"author\":{\"name\":\"Brett Lawson, Principal Software Engineer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f\"},\"headline\":\"Game Servers and Couchbase with Node.js &#8211; Part 3\",\"datePublished\":\"2014-12-16T19:32:07+00:00\",\"dateModified\":\"2023-06-28T07:23:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/\"},\"wordCount\":2047,\"commentCount\":6,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/\",\"name\":\"Game Servers and Couchbase with Node.js - Part 3 - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-16T19:32:07+00:00\",\"dateModified\":\"2023-06-28T07:23:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Game Servers and Couchbase with Node.js &#8211; Part 3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f\",\"name\":\"Brett Lawson, Principal Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ee3586f0c112c20e863af447d44dec8f\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g\",\"caption\":\"Brett Lawson, Principal Software Engineer, Couchbase\"},\"description\":\"Brett Lawson is a Principal Software Engineer at Couchbase. Brett is responsible for the design and development of the Couchbase Node.js and PHP clients as well as playing a role in the design and development of the C library, libcouchbase.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/brett-lawson\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Game Servers and Couchbase with Node.js - Part 3 - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-3\/","og_locale":"pt_BR","og_type":"article","og_title":"Game Servers and Couchbase with Node.js - Part 3","og_description":"In this part of the series, we will be setting up a game data storage system to allow you to store player game state over the course of their enjoyment of your game. To do this, we are going to [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/game-servers-and-couchbase-nodejs-part-3\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-16T19:32:07+00:00","article_modified_time":"2023-06-28T07:23:43+00:00","author":"Brett Lawson, Principal Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Brett Lawson, Principal Software Engineer, Couchbase","Est. reading time":"10 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/"},"author":{"name":"Brett Lawson, Principal Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f"},"headline":"Game Servers and Couchbase with Node.js &#8211; Part 3","datePublished":"2014-12-16T19:32:07+00:00","dateModified":"2023-06-28T07:23:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/"},"wordCount":2047,"commentCount":6,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/","url":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/","name":"Game Servers and Couchbase with Node.js - Part 3 - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-16T19:32:07+00:00","dateModified":"2023-06-28T07:23:43+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/game-servers-and-couchbase-nodejs-part-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Game Servers and Couchbase with Node.js &#8211; Part 3"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5cfc2fbf25776be2a027a474562be02f","name":"Brett Lawson, engenheiro de software principal, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ee3586f0c112c20e863af447d44dec8f","url":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g","caption":"Brett Lawson, Principal Software Engineer, Couchbase"},"description":"Brett Lawson \u00e9 engenheiro de software principal da Couchbase. Brett \u00e9 respons\u00e1vel pelo projeto e desenvolvimento dos clientes Node.js e PHP do Couchbase, al\u00e9m de desempenhar um papel no projeto e desenvolvimento da biblioteca C, libcouchbase.","url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/brett-lawson\/"}]}},"authors":[{"term_id":9004,"user_id":31,"is_guest":0,"slug":"brett-lawson","display_name":"Brett Lawson, Principal Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/6aec1ba24ef7558a248dcde7b7a18b15b06e2885b24b663906a448634066c1c4?s=96&d=mm&r=g","author_category":"","last_name":"Lawson","first_name":"Brett","job_title":"","user_url":"","description":"Brett Lawson \u00e9 engenheiro de software principal da Couchbase. Brett \u00e9 respons\u00e1vel pelo projeto e desenvolvimento dos clientes Node.js e PHP do Couchbase, al\u00e9m de desempenhar um papel no projeto e desenvolvimento da biblioteca C, libcouchbase."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1616","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=1616"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1616\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=1616"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=1616"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=1616"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=1616"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}