Nos últimos dias, exploramos como criar um aplicativo simples para Android e iOS usando NativeScript, Angular e Couchbase. Primeiro, vimos como usar o Couchbase para operações básicas de valor-chave e então vimos como consultar o Couchbase como um banco de dados de documentos. O capítulo final é adicionar suporte de replicação ao nosso aplicativo NativeScript usando o Couchbase Sync Gateway.
Vamos expandir os dois exemplos anteriores para sincronizar dados entre plataformas e dispositivos usando o Couchbase Sync Gateway, NativeScript e Angular. Veja a seguinte imagem animada, por exemplo:

Quando um novo perfil é adicionado ao dispositivo iOS, ele é sincronizado com o dispositivo Android e, da mesma forma, na direção oposta. Isso é possível com muito pouco código.
Os requisitos
Os requisitos entre este exemplo e os dois anteriores mudaram um pouco. Para ter sucesso, você precisará do seguinte:
- NativeScript 2.0+
- Gateway de sincronização do Couchbase
O NativeScript, o Angular e o plug-in do Couchbase Lite podem ser obtidos por meio da CLI do NativeScript. Não sincronizaremos nossos dados com o Couchbase Server neste exemplo, mas podemos fazer isso facilmente com poucas alterações.
Continuando de onde paramos
Para ter sucesso com este tutorial, você precisará ter visto Parte 2 que tem sua própria dependência de ter visualizado Parte 1. A maior parte do código desses guias anteriores pode ser copiada e colada em um projeto.
Antes de continuar, você deverá ter um aplicativo NativeScript funcional de duas páginas com uma caixa de diálogo modal. Os dados desse aplicativo são salvos em Couchbase e consultados usando exibições do MapReduce.
Criação de um serviço Angular para o Couchbase
Como a replicação de dados estará envolvida, precisamos nos certificar de que temos apenas uma única instância do Couchbase em execução no nosso aplicativo. No exemplo anterior, criamos uma nova instância por página. Não podemos fazer isso com a replicação porque podemos acabar replicando várias vezes, o que é ineficiente.
Para criar uma instância singleton do Couchbase, devemos criar um serviço Angular. Crie um arquivo em seu projeto em app/couchbase.service.ts e inclua o seguinte código TypeScript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
importação { Injetável } de "@angular/core"; importação { Couchbase } de "nativescript-couchbase"; @Injetável() exportação classe CouchbaseService { privado banco de dados: qualquer; privado puxar: qualquer; privado empurrar: qualquer; público construtor() { } público getDatabase() { } público startSync(portal: string, contínuo: booleano) { } público stopSync() { } } |
Esse serviço poderá ser injetado em todas as páginas. Uma única instância do Couchbase será armazenada no diretório banco de dados
e as informações sobre os replicadores push e pull serão armazenadas em suas respectivas variáveis.
Dentro do construtor
temos o seguinte:
1 2 3 4 5 6 7 8 |
público construtor() { se(!este.banco de dados) { este.banco de dados = novo Couchbase("dados"); este.banco de dados.createView("perfis", "1", função(documento, emissor) { emissor.emitir(documento._id, documento); }); } } |
Antes de criar uma nova instância do Couchbase, verificamos se já não temos uma. Caso contrário, abrimos o banco de dados e criamos uma visualização MapReduce, que não é nada que já não tenhamos visto nos exemplos anteriores.
1 2 3 |
público getDatabase() { retorno este.banco de dados; } |
Quando chegar a hora de obter essa instância, podemos retorná-la por meio do getDatabase
função. Isso nos leva à replicação de dados.
1 2 3 4 5 6 7 8 9 10 |
público startSync(portal: string, contínuo: booleano) { este.empurrar = este.banco de dados.createPushReplication(portal); este.puxar = este.banco de dados.createPullReplication(portal); este.empurrar.setContinuous(contínuo); este.puxar.setContinuous(contínuo); este.empurrar.iniciar(); este.puxar.iniciar(); } |
Para este exemplo, faremos uma sincronização bidirecional com uma instância do Sync Gateway. Temos a opção de sincronizar uma vez ou continuamente enquanto o aplicativo estiver aberto. Quando quisermos interromper a replicação, podemos usar a opção stopSync
vista abaixo:
1 2 3 4 |
público stopSync() { este.empurrar.parar(); este.puxar.parar(); } |
Como esse será um serviço compartilhado, ele precisa ser injetado no @NgModule
bloco. Abra a seção app/app.module.ts e inclua o seguinte TypeScript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
importação { NgModule, NÃO_ERROS_ESQUEMA } de "@angular/core"; importação { NativeScriptModule } de "nativescript-angular/platform"; importação { NativeScriptFormsModule } de "nativescript-angular/forms"; importação { NativeScriptRouterModule } de "nativescript-angular/router"; importação { ModalDialogService } de "nativescript-angular/modal-dialog"; importação { Componentes do aplicativo, Rotas de aplicativos } de "./app.routing"; importação { Componente de aplicativo } de "./app.component"; importação { Componente Modal } de "./app.modal"; importação { CouchbaseService } de "./couchbase.service"; @NgModule({ declarações: [Componente de aplicativo, Componente Modal, ...Componentes do aplicativo], entryComponents: [Componente Modal], bootstrap: [Componente de aplicativo], importações: [ NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(Rotas de aplicativos) ], provedores: [ModalDialogService, CouchbaseService], esquemas: [NO_ERRORS_SCHEMA] }) exportação classe AppModule { } |
O exemplo acima é o que vimos anteriormente, mas desta vez importamos o CouchbaseService
e o injetou no provedores
matriz do @NgModule
bloco.
Agora, cada uma de nossas páginas pode ser atualizada para usar o novo serviço do Angular.
Atualização das páginas do aplicativo NativeScript
Temos duas páginas que precisam ser atualizadas para refletir nosso serviço do Angular. Abra a seção app/components/profile-list/profile-list.ts e remova o código do Couchbase encontrado no arquivo construtor
método. Em vez disso, o arquivo deve se parecer com o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
importação { Componente, OnInit, OnDestroy, NgZone } de "@angular/core"; importação { Localização } de "@angular/common"; importação { Roteador } de "@angular/router"; importação { CouchbaseService } de "../../couchbase.service"; @Componente({ seletor: "profile-list" (lista de perfis), templateUrl: "./components/profile-list/profile-list.html", }) exportação classe Componente ProfileList implementa OnInit, OnDestroy { público perfis: Matriz; privado banco de dados: qualquer; público construtor(privado roteador: Roteador, privado localização: Localização, privado zona: NgZone, privado couchbase: CouchbaseService) { este.banco de dados = este.couchbase.getDatabase(); este.perfis = []; } público ngOnInit() { este.localização.assinar(() => { este.atualizar(); }); este.atualizar(); } público atualizar() { este.perfis = []; deixar linhas = este.banco de dados.executeQuery("perfis"); para(deixar i = 0; i < linhas.comprimento; i++) { este.perfis.empurrar(linhas[i]); } } público criar() { este.roteador.navegar(["profile" (perfil)]); } } |
Observe no exemplo acima que importamos CouchbaseService
e o injetou no construtor
juntamente com o método NgZone
. Em vez de obter o banco de dados e criar uma exibição, precisamos apenas chamar o comando getDatabase
função do nosso serviço.
Até agora, nada de ruim, certo?
Agora vamos abrir o arquivo app/components/profile/profile.ts arquivo. Nesse arquivo, inclua o seguinte código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
importação { Componente, ViewContainerRef } de "@angular/core"; importação { Localização } de "@angular/common"; importação { ModalDialogService } de "nativescript-angular/directives/dialogs"; importação { CouchbaseService } de "../../couchbase.service"; importação { Componente Modal } de "../../app.modal"; @Componente({ seletor: "profile" (perfil), templateUrl: "./components/profile/profile.html", }) exportação classe ProfileComponent { público perfil: qualquer; privado banco de dados: qualquer; público construtor(privado modal: ModalDialogService, privado vcRef: ViewContainerRef, privado localização: Localização, privado couchbase: CouchbaseService) { este.perfil = { foto: "~/kitten1.jpg", primeiro nome: "", sobrenome: "" } este.banco de dados = este.couchbase.getDatabase(); } público showModal(tela cheia: booleano) { deixar opções = { contexto: { promptMsg: "Escolha seu avatar!" }, tela cheia: tela cheia, viewContainerRef: este.vcRef }; este.modal.showModal(Componente Modal, opções).então((res: string) => { este.perfil.foto = res || "~/kitten1.jpg"; }); } público salvar() { este.banco de dados.createDocument(este.perfil); este.localização.voltar(); } } |
Com exceção de NgZone
Na página anterior, fizemos a mesma alteração no Couchbase que fizemos na página anterior. Veremos o que NgZone
em breve.
Nesse ponto, podemos prosseguir com a configuração do Sync Gateway para preparar a sincronização de dados.
Criação da configuração de replicação do Sync Gateway
Você já deve ter feito o download de Gateway de sincronização do Couchbase até agora. Com ele instalado, precisamos criar um arquivo de configuração para o nosso projeto. A seguir, um exemplo de uma configuração muito simples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "log":["CRUD+", "REST+", "Mudanças+", "Anexar+"], "bancos de dados": { "exemplo": { "servidor":"walrus:", "sync":` função (doc) { canal (doc.canais); } `, "usuários": { "CONVIDADO": { "desativado": falso, "admin_channels": ["*"] } } } } } |
A configuração acima pode ser salva em um arquivo chamado sync-gateway-config.json ou similar. Essencialmente, ele usa um armazenamento na memória chamado morsa:
com um nome de banco de dados de exemplo
. Não há permissões de leitura ou gravação em nosso exemplo. Todos os dados serão sincronizados em todas as plataformas e dispositivos.
Conectar o Sync Gateway ao Couchbase Server é tão simples quanto alterar morsa:
para o host de sua instância do Couchbase Server.
Para executar o Sync Gateway a partir da linha de comando, você deve executar:
1 |
/caminho/para/portais de sincronização /caminho/para/sincronização-portal-configuração.json |
Ele criará um painel que pode ser acessado em http://localhost:4985/_admin/. No nível do aplicativo, ele usará a porta 4984.
Incluindo a lógica de sincronização para Couchbase e NativeScript
Tudo está completo na preparação da replicação de dados em nosso aplicativo. A replicação de dados nos permitirá usar ouvintes de alterações para atualizar nossa interface do usuário conforme necessário.
Abra o arquivo app/components/profile-list/profile-list.ts e inclua o seguinte no ngOnInit
método:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
público ngOnInit() { este.localização.assinar(() => { este.atualizar(); }); este.couchbase.startSync("http://192.168.57.1:4984/example", verdadeiro); este.banco de dados.addDatabaseChangeListener((mudanças) => { para (deixar i = 0; i < mudanças.comprimento; i++) { deixar documento = este.banco de dados.getDocument(mudanças[i].getDocumentId()); este.zona.executar(() => { este.perfis.empurrar(documento); }); } }); este.atualizar(); } |
Quando o ngOnInit
iniciamos a sincronização com nosso Sync Gateway em execução local. Sinta-se à vontade para definir o nome do host para o que for mais adequado para você. Depois de iniciarmos a sincronização, configuramos nosso ouvinte de alterações para enviar as alterações para o nosso perfis
array. Como se trata de um ouvinte, precisamos usar NgZone
caso contrário, ele não será refletido na interface do usuário.
O exemplo acima é apenas um exemplo simples em que adicionamos todas as alterações. Na realidade, você precisará verificar se os dados foram alterados, criados ou excluídos. Todos os cenários viriam por meio da função addDatabaseChangeListener
.
Quando o aplicativo for interrompido, queremos interromper a sincronização de forma graciosa. Na seção ngOnDestroy
inclua o seguinte:
1 2 3 |
público ngOnDestroy() { este.couchbase.stopSync(); } |
A replicação para o Couchbase Sync Gateway será interrompida quando o método Angular acima for chamado.
Conclusão
Neste tutorial, você viu como adicionar suporte de sincronização ao seu aplicativo móvel Angular NativeScript. Essa foi a terceira parte de três da série de tutoriais. Anteriormente, vimos como fazer operações básicas do Couchbase para salvar e carregar dados bem como consulta de documentos. Data no desenvolvimento de aplicativos móveis usando estruturas como NativeScript e o Angular devem ser fáceis. Ser capaz de armazenar objetos JavaScript e dados JSON em um banco de dados NoSQL e sincronizá-los é um grande fardo para o desenvolvedor.
Obrigado por essa série de tutoriais, ela é muito boa. Consegui fazer com que ela funcionasse entre um dispositivo Android e iOS e é muito simples. Neste exemplo, eu estava basicamente usando o Sync Gateway no meu Mac como um intermediário com o qual os outros dispositivos da rede estão sincronizando.
Gostaria de usar esse recurso de sincronização para um aplicativo móvel que terá vários dispositivos na mesma rede e gostaria que ele funcionasse no modo off-line, portanto, será necessário ter uma função separada para várias redes diferentes. Existe uma maneira de configurar um Sync Gateway apenas entre dispositivos móveis em uma rede sem precisar configurá-lo em um computador na rede? Ou precisarei fazer com que cada rede instale e configure seu próprio Sync Gateway com os arquivos de configuração do sync-gateway que eu fornecer?
Há suporte a P2P nas APIs subjacentes do Android e do iOS, mas ele nunca foi adicionado ao plug-in do NativeScript.
O Couchbase Lite 2.0 será lançado em breve, portanto, as coisas estarão mudando. Se você puder, leia sobre o assunto e aguarde um pouco.
Obrigado pela resposta rápida, Nic. Você sabe se algum desses novos recursos de P2P será incorporado ao plug-in do NativeScript?
Olá Nic, tenho uma pergunta: estou tentando armazenar um documento usando o couchbase lite com nativescript em um projeto que estou criando, mas, de alguma forma, minha lógica não está funcionando. Gostaria de saber se você poderia dar uma olhada no meu código e me informar se estou fazendo algo errado. Este é um link para meu código: https://i.gyazo.com/99914e2c1c54b37ea7486ff050bc6dd0.pngObrigado desde já.