pouchdb

Dicas para trabalhar com o Ionic Framework – PouchDB

Originalmente essa era pra ser só mais uma dica para se trabalhar com o Ionic, e viria acompanhada de diversas outras, mas eu decidi discorrer sobre o assunto para poder argumentar e expressar os motivos pelos quais eu escolhi trabalhar com o PouchDB em meus apps.

Introdução

Quando pensamos em persistência de dados em dispositivos móveis logo pensamos no SQLite, mas as vezes uma mudança de paradigma pode tornar o desenvolvimento mais fácil.

Quando comecei a desenvolver com o Ionic eu tinha alguns requisitos básicos e um deles era sincronização com servidor sem complicação. Então eu queria ser capaz de persistir os dados no dispositivo móvel e quando necessário sincronizar com o servidor sem esquentar muito a cabeça com estratégias de sincronização.

E foi nesse contexto que conheci o PouchDB. O PouchDB é um SGBD não relacional, o famoso NoSQL, baseado em documentos que busca ser uma implementação em JavaScript do CouchdDB. O motivo dele seguir a mesma API do CouchDB é o fato dele ter sido concebido para sincronizar com o CouchDB como se fosse uma outra instância do CouchDB.

Como o PouchDB faz uso do IndexedDB e/ou do WebSQL para armazenamento dos dados ele possui uma limitação de tamanho máximo determinada por cada browser. Por isso é interessante utilizarmos ele em conjunto com o SQLite, pois o SQLite não possui tais limitações. O PouchDB irá utilizar o SQLite automaticamente caso você tenha instalado o plugin do mesmo através do comando:

cordova plugin add io.litehelpers.cordova.sqlitestorage

E para instalar o PouchDB nós utilizamos o bower:

bower install pouchdb --save

E depois importamos o mesmo em nosso index.html:

<script src="lib/pouchdb/dist/pouchdb.min.js"></script>

Trabalhar com o PouchDB é relativamente fácil e ele possui um guia básico bem completo em seu site.

Quem já trabalhou com o Mongo não terá muitos problemas para se habituar com o PouchDB, as diferenças mais gritantes entre os dois são: o protocolo de comunicação, o CouchDB utiliza o protocolo HTTP para realizar suas operações; e o fato do CouchDB não possuir Collections como o Mongo, ou seja, todos os documentos são armazenados no mesmo “nível” e nós precisamos de uma outra ferramenta para identificar o tipo daquele documento. E é aí que entram as Persistent Queries.

Mas isso é conversa pra um artigo mais aprofundado sobre o assunto. E o foco desse texto é mostrar o quão simples é sincronizar dois bancos de dados utilizando o PouchDB.

Atualmente o Couchbase e o Cloudant são outras plataformas de banco de dados que compartilham o mesmo protocolo de sincronização. Isso significa que o PouchDB também é capaz de sincronizar com essas plataformas.

Sincronização

É possível sincronizar os dados entre dois ou mais bancos através da replicação, ou replication, onde estamos replicando um banco para outro banco, ou seja, criando uma “cópia”.

var localDB = new PouchDB('mylocaldb')
var remoteDB = new PouchDB('http://localhost:5984/myremotedb')

localDB.replicate.to(remoteDB).on('complete', function () {
  // Sincronizado!
}).on('error', function (err) {
  // Ops, tivemos um erro!
});

No exemplo acima estamos replicando os dados do banco local para o banco remoto, porém o contrário (do remoto para o local não acontece). Replicamos do remoto para o local utilizando o replicate.from:

var localDB = new PouchDB('mylocaldb');
var remoteDB = new PouchDB('http://localhost:5984/myremotedb');

localDB.replicate.from(remoteDB).on('complete', function () {
  // Sincronizado!
}).on('error', function (err) {
  // Ops, tivemos um erro!
});

Nesse caso estamos replicando do banco remoto para o local. Mas e se quisermos sincronizar tudo? Enviar as alterações do local para o remoto e as alterações do remoto para o local?

localDB.replicate.to(remoteDB);
localDB.replicate.from(remoteDB);

No entanto, o PouchDB possui um atalho pra tornar ainda mais fácil esse caso específico:

localDB.sync(remoteDB).on('complete', function () {
  // Sincronizado!
}).on('error', function (err) {
  // Ops, tivemos um erro!
});

Mas e se quisermos manter os dois bancos sempre sincronizados?

localDB.sync(remoteDB, {
  live: true
}).on('change', function () {
  // Ocorreu uma alteração!
}).on('error', function (err) {
  // Ops, tivemos um erro!
});

No entanto, quando o usuário ficar offline nós teremos um erro e a sincronização será quebrada. Para resolver esse problema nós precisamos dizer ao PouchDB para tentar novamente:

localDB.sync(remoteDB, {
  live: true,
  retry: true
}).on('change', function (change) {
  // Ocorreu uma alteração!
}).on('paused', function (info) {
  // replicação pausada, normalmente por que o usuário está offline
}).on('active', function (info) {
  // replicação continuada
}).on('error', function (err) {
  // erro desconhecido, normalmente não deveria acontecer
})));

Também é possível sincronizar apenas partes específicas do nosso banco utilizando as Persistent Queries, mas vou deixar para uma próxima oportunidade.

Conclusão

Uma abordagem não relacional pode não encaixar em todos os tipos de aplicações e normalmente essa mudança de paradigma em nossa forma de desenvolver leva certo tempo para assimilação, então temos que saber pesar as vantagens e desvantagens de utilizar de cada tipo de banco de dados para podermos extrair o melhor de cada.

Para entender melhor como funciona essa abordagem dos bancos não relacionais baseados em documentos eu recomendo esses artigos do Jean Carlo Nascimento (@osuissa):

MongoDb – Como mudar seu jeito relacional de pensar – Parte 1

MongoDb – Como mudar seu jeito relacional de pensar – Parte 2

Aprendendo MongoDb a partir do Relacional

Jean Lucas de Carvalho

Instrutor at Futuring
Desenvolvedor Front-end na HE:labs e instrutor na Futuring, especialista em aplicativos híbridos com Cordova e Ionic Framework, faxineiro do Frontend Goiás, ex-subcelebridade do Google Developer Bus Brazil, sedentário e o lindão ali da foto. Tudo isso quando não está com preguiça demais pra fazer alguma coisa.

Latest posts by Jean Lucas de Carvalho (see all)

Comentários