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
:
http://lib/pouchdb/dist/pouchdb.min.js
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