{"id":2480,"date":"2017-01-01T15:00:00","date_gmt":"2017-01-01T15:00:00","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2480"},"modified":"2025-06-13T20:15:36","modified_gmt":"2025-06-14T03:15:36","slug":"syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/","title":{"rendered":"Sincronizaci\u00f3n con Couchbase en una app Ionic 2 usando PouchDB"},"content":{"rendered":"<p>No hace mucho escrib\u00ed sobre el uso de <a href=\"https:\/\/www.couchbase.com\/blog\/es\/data-synchronization-with-couchbase-in-ionic-2-hybrid-mobile-apps\/\">Couchbase en una aplicaci\u00f3n Ionic 2<\/a>. En el ejemplo anterior vimos c\u00f3mo usar Couchbase Lite y la API RESTful para guardar datos y trabajar con Couchbase Sync Gateway. Aunque ese es el enfoque preferido, no es el \u00fanico.<\/p>\n<p>Existe una magn\u00edfica biblioteca JavaScript llamada <a href=\"https:\/\/pouchdb.com\/\">PouchDB<\/a> que realmente puede conectarse a Couchbase Sync Gateway, sacando a Couchbase Lite de la ecuaci\u00f3n. Esto significa que PouchDB se puede utilizar con Ionic 2 para sincronizar datos entre Couchbase Server y cualquier aplicaci\u00f3n que se haya creado.<\/p>\n<p>\u00bfC\u00f3mo podemos conseguirlo?<\/p>\n<h2 id=\"the-requirements\">Requisitos<\/h2>\n<p>Si viste el tutorial anterior, los requisitos aqu\u00ed no ser\u00e1n diferentes. Son los siguientes:<\/p>\n<ul>\n<li>Node.js 4.0+<\/li>\n<li><a href=\"https:\/\/www.ionicframework.com\">Marco i\u00f3nico<\/a> 2.0<\/li>\n<li>Pasarela de sincronizaci\u00f3n Couchbase<\/li>\n<li>Android SDK para Android y Xcode para iOS<\/li>\n<\/ul>\n<p>La CLI de Ionic Framework 2.0 se utiliza para crear y construir aplicaciones. Utiliza el Node Package Manager (NPM) que se encuentra con Node.js para descargar todas las dependencias. En este ejemplo no sincronizaremos con Couchbase Server, pero usaremos Couchbase Sync Gateway. El plan aqu\u00ed es hacer uso de la opci\u00f3n in-memory que Sync Gateway tiene para prototipado. Incluir Couchbase Server no es dif\u00edcil despu\u00e9s de esto.<\/p>\n<h2 id=\"preparing-couchbase-sync-gateway\">Preparaci\u00f3n de Couchbase Sync Gateway<\/h2>\n<p>Couchbase Sync Gateway maneja toda la orquestaci\u00f3n de datos entre dispositivos, plataformas y Couchbase Server. Esto incluye cualquier permiso de lectura y escritura. Debido a esto necesita tener su propia configuraci\u00f3n basada en las necesidades de tu aplicaci\u00f3n.<\/p>\n<p>Tomemos como ejemplo la siguiente configuraci\u00f3n:<\/p>\n<pre><code>{\r\n    \"log\":[\"CRUD+\", \"REST+\", \"Changes+\", \"Attach+\"],\r\n    \"databases\": {\r\n        \"example\": {\r\n            \"server\":\"walrus:\",\r\n            \"sync\":`\r\n                function (doc) {\r\n                    channel (doc.channels);\r\n                }\r\n            `,\r\n            \"users\": {\r\n                \"GUEST\": {\r\n                    \"disabled\": false,\r\n                    \"admin_channels\": [\"*\"]\r\n                }\r\n            }\r\n        }\r\n    },\r\n    \"CORS\": {\r\n        \"Origin\": [\"https:\/\/localhost:8100\"],\r\n        \"LoginOrigin\": [\"https:\/\/localhost:8100\"],\r\n        \"Headers\": [\"Content-Type\"],\r\n        \"MaxAge\": 17280000\r\n    }\r\n}<\/code><\/pre>\n<p>La configuraci\u00f3n anterior crea una base de datos llamada <strong>ejemplo<\/strong> sin reglas en cuanto a la canalizaci\u00f3n de datos. Esto significa que todos los dispositivos podr\u00e1n leer y escribir. Tus necesidades pueden ser distintas.<\/p>\n<p>En la parte inferior de la configuraci\u00f3n hay informaci\u00f3n sobre el uso compartido de recursos entre or\u00edgenes (CORS). La parte inferior no es necesaria a menos que planee utilizar funciones como <code>servicio i\u00f3nico<\/code>. Si se intenta acceder a Sync Gateway desde el mismo host, pero desde un puerto diferente, se producir\u00e1n errores de JavaScript. La adici\u00f3n de CORS evitar\u00e1 esto. Una vez m\u00e1s, esto es s\u00f3lo si desea servir la aplicaci\u00f3n en su navegador web. Ejecutar la aplicaci\u00f3n desde su dispositivo no tendr\u00e1 problemas.<\/p>\n<h2 id=\"creating-an-ionic-framework-with-pouchdb-application\">Creaci\u00f3n de una aplicaci\u00f3n Ionic Framework con PouchDB<\/h2>\n<p>La aplicaci\u00f3n que crearemos ser\u00e1 igual a la que creamos anteriormente con Couchbase Lite y Ionic 2. Vamos a crear una sencilla aplicaci\u00f3n de lista de tareas que sincroniza los elementos entre dispositivos.<\/p>\n<div class=\"figure\"><img decoding=\"async\" src=\"\/wp-content\/original-assets\/2017\/january\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/pouchdb-ionic2-cbmobile.gif\" alt=\"Couchbase with Ionic 2 and PouchDB\" \/><\/div>\n<p>Esta es una aplicaci\u00f3n de una sola p\u00e1gina, pero cubre todas las mejores pr\u00e1cticas necesarias de Ionic 2 y Angular 2. Para crear este proyecto, ejecuta lo siguiente desde tu S\u00edmbolo del sistema (Windows) o Terminal (Mac y Linux):<\/p>\n<pre><code>ionic start PouchDBProject blank --v2\r\ncd PouchDBProject\r\nplataforma ionic add ios\r\nplataforma ionic add android<\/code><\/pre>\n<p>Los comandos anteriores crear\u00e1n un nuevo proyecto Ionic 2 que utiliza Angular 2 y TypeScript. Aunque he a\u00f1adido las plataformas de compilaci\u00f3n de Android e iOS, no podr\u00e1s compilar para iOS a menos que utilices un Mac con Xcode instalado.<\/p>\n<p>Dado que este proyecto utilizar\u00e1 <a href=\"https:\/\/pouchdb.com\/\">PouchDB<\/a>es necesario instalarlo en nuestro proyecto. Esto se puede hacer ejecutando el siguiente comando:<\/p>\n<pre><code>npm install pouchdb --save<\/code><\/pre>\n<p>PouchDB es un proyecto JavaScript y no tiene soporte adecuado para TypeScript. Esto no es un problema ya que podemos sortear el obst\u00e1culo de la falta de definiciones de tipo. Sin embargo, vamos a necesitar obtener definiciones de tipos para otra librer\u00eda que cargar\u00e1 el plugin.<\/p>\n<p>Desde la l\u00ednea de comandos, ejecute lo siguiente:<\/p>\n<pre><code>npm install @tipo\/nodo --save<\/code><\/pre>\n<p>La instalaci\u00f3n de las definiciones de tipos de Node.js nos permitir\u00e1 utilizar la funci\u00f3n <code>requiere<\/code> que es esencial cuando se importan dependencias de JavaScript.<\/p>\n<p>Hay una dependencia m\u00e1s de JavaScript para nuestro proyecto, pero esta vez no tenemos que preocuparnos de que las definiciones de tipo no existan. Necesitamos instalar una librer\u00eda para generar valores id \u00fanicos que representar\u00e1n nuestras claves de documento. Esta librer\u00eda puede ser instalada a trav\u00e9s del siguiente comando:<\/p>\n<pre><code>npm install uuid @type\/uuid --save<\/code><\/pre>\n<p>El comando anterior instalar\u00e1 la biblioteca y sus definiciones de tipos para TypeScript.<\/p>\n<p>En este punto podemos centrarnos en el desarrollo de nuestra aplicaci\u00f3n.<\/p>\n<h3 id=\"developing-the-angular-2-shared-provider\">Desarrollo del proveedor compartido de Angular 2<\/h3>\n<p>Es una buena pr\u00e1ctica en cualquier aplicaci\u00f3n Angular 2 mantener la actividad relacionada con la base de datos separada en lo que se conoce como un proveedor compartido o servicio compartido. Esto nos permite tener una instancia de base de datos singleton y mantener nuestro c\u00f3digo de base de datos fuera de la l\u00f3gica de la p\u00e1gina.<\/p>\n<p>Para crear un proveedor en Ionic 2, ejecute el siguiente comando:<\/p>\n<pre><code>proveedor de ionic g pouchdb-provider<\/code><\/pre>\n<p>El comando anterior deber\u00eda crear un archivo en <strong>src\/providers\/pouchdb-provider.ts<\/strong> con el que podamos trabajar. Abra este nuevo archivo e incluya el siguiente c\u00f3digo:<\/p>\n<pre><code>import { Injectable, EventEmitter } from '@angular\/core';\r\nvar PouchDB = require(\"pouchdb\");\r\n\r\n@Injectable()\r\nexport class PouchDBProvider {\r\n\r\n    private isInstantiated: boolean;\r\n    private database: any;\r\n    private listener: EventEmitter = new EventEmitter();\r\n\r\n    public constructor() { }\r\n\r\n    public fetch() { }\r\n\r\n    public get(id: string) { }\r\n\r\n    public put(document: any, id: string) { }\r\n\r\n    public sync(remote: string) { }\r\n\r\n    public getChangeListener() { }\r\n\r\n}<\/code><\/pre>\n<p>Antes de empezar a rellenar cada uno de los m\u00e9todos, vamos a desglosar lo que tenemos hasta ahora.<\/p>\n<p>Este proveedor ser\u00e1 inyectable en cada una de las p\u00e1ginas que deseemos utilizarlo. Dado que PouchDB nos permite sincronizar cambios, queremos ser capaces de emitir esos cambios y suscribirnos a ellos, de ah\u00ed la necesidad del m\u00f3dulo <code>Emisor de eventos<\/code> importar. La biblioteca PouchDB se importa como JavaScript est\u00e1ndar.<\/p>\n<p>S\u00f3lo queremos mantener abierta una instancia de la base de datos y podemos hacerlo utilizando una funci\u00f3n <code>isInstantiated<\/code> variable. Esto se hace en el <code>constructor<\/code> as\u00ed:<\/p>\n<pre><code>public constructor() {\r\n    if(!this.isInstantiated) {\r\n        this.database = new PouchDB(\"nraboy\");\r\n        this.isInstantiated = true;\r\n    }\r\n}<\/code><\/pre>\n<p>Con una base de datos abierta queremos ser capaces de trabajar con los datos. PouchDB tiene sus propias APIs para trabajar con datos, pero siendo que es vanilla JavaScript, ciertas cosas deben ser mejoradas en nuestro proveedor para hacerlo m\u00e1s amigable con Angular 2.<\/p>\n<pre><code>public fetch() {\r\n    return this.database.allDocs({include_docs: true});\r\n}<\/code><\/pre>\n<p>La obtenci\u00f3n de todos los datos puede realizarse mediante la funci\u00f3n <code>allDocs<\/code> en PouchDB. Al incluir el m\u00e9todo <code>incluir_docs<\/code> se incluyen los datos del documento en lugar de s\u00f3lo los valores de id.<\/p>\n<pre><code>public get(id: cadena) {\r\n    return this.database.get(id);\r\n}<\/code><\/pre>\n<p>Si conoce el identificador del documento que busca, puede buscarlo directamente en lugar de consultar todos los documentos. Guardar documentos es donde las cosas se pueden poner un poco confusas:<\/p>\n<pre><code>public put(document: any, id: string) {\r\n    document._id = id;\r\n    return this.get(id).then(result =&gt; {\r\n        document._rev = result._rev;\r\n        return this.database.put(document);\r\n    }, error =&gt; {\r\n        if(error.status == \"404\") {\r\n            return this.database.put(document);\r\n        } else {\r\n            return new Promise((resolve, reject) =&gt; {\r\n                reject(error);\r\n            });\r\n        }\r\n    });\r\n}<\/code><\/pre>\n<p>En el <code>poner<\/code> tenemos un m\u00e9todo para crear o actualizar un documento. Los documentos que no tienen revisi\u00f3n se crean, en caso contrario se actualizan. Esto es posible haciendo primero una b\u00fasqueda en un documento por su id. Si el documento existe, se utiliza la revisi\u00f3n y se actualiza, en caso contrario se crea.<\/p>\n<pre><code>public sync(remote: string) {\r\n    let remoteDatabase = new PouchDB(remote);\r\n    this.database.sync(remoteDatabase, {\r\n        live: true\r\n    }).on('change', change =&gt; {\r\n        this.listener.emit(change);\r\n    }).on('error', error =&gt; {\r\n        console.error(JSON.stringify(error));\r\n    });\r\n}<\/code><\/pre>\n<p>Sin sincronizaci\u00f3n no est\u00e1s t\u00e9cnicamente usando Couchbase en tu pila. Adem\u00e1s, hay soluciones mucho mejores para los datos que PouchDB si s\u00f3lo est\u00e1s buscando una base de datos local. Dicho esto, lo anterior <code>sincronizar<\/code> le permitir\u00e1 conectarse a una base de datos remota. Nuestra base de datos remota es en realidad una instancia de Sync Gateway en ejecuci\u00f3n. Estamos optando por hacer una sincronizaci\u00f3n bidireccional con Sync Gateway y la emisi\u00f3n de los cambios a la <code>Emisor de eventos<\/code> en Angular 2.<\/p>\n<pre><code>public getChangeListener() {\r\n    return this.listener;\r\n}<\/code><\/pre>\n<p>Cuando deseamos suscribirnos a esos cambios, primero debemos obtener una copia del oyente que los emite.<\/p>\n<p>En este punto el proveedor de Angular 2 est\u00e1 completo, pero no listo para ser utilizado. Es necesario a\u00f1adir el proyecto de <code>@NgModule<\/code> que se encuentra en el bloque <strong>src\/app\/app.module.ts<\/strong> archivo. El archivo tendr\u00eda un aspecto similar al siguiente<\/p>\n<pre><code>import { NgModule, ErrorHandler } from '@angular\/core';\r\nimport { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';\r\nimport { MyApp } from '.\/app.component';\r\nimport { HomePage } from '..\/pages\/home\/home';\r\nimport { PouchDBProvider } from \"..\/providers\/pouchdb-provider\";\r\n\r\n@NgModule({\r\n    declarations: [\r\n        MyApp,\r\n        HomePage\r\n    ],\r\n    imports: [\r\n        IonicModule.forRoot(MyApp)\r\n    ],\r\n    bootstrap: [IonicApp],\r\n    entryComponents: [\r\n        MyApp,\r\n        HomePage\r\n    ],\r\n    providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, PouchDBProvider]\r\n})\r\nexport class AppModule {}<\/code><\/pre>\n<p>F\u00edjese en c\u00f3mo se import\u00f3 el proveedor y luego se a\u00f1adi\u00f3 a la carpeta <code>proveedores<\/code> array. Ahora se puede utilizar en cada p\u00e1gina de nuestra aplicaci\u00f3n.<\/p>\n<h3 id=\"adding-pouchdb-logic-for-saving-and-syncing\">A\u00f1adir l\u00f3gica PouchDB para guardar y sincronizar<\/h3>\n<p>El resto de nuestra aplicaci\u00f3n es en realidad bastante simple ahora que hemos sentado las bases de nuestro <a href=\"https:\/\/www.couchbase.com\/blog\/es\/resources\/concepts\/data-platforms\/\">capa de datos<\/a>. Recuerde que se trata de una aplicaci\u00f3n muy sencilla, pero muy orientada a los datos.<\/p>\n<p>Abra el archivo <strong>src\/pages\/home\/home.ts<\/strong> e incluya el siguiente c\u00f3digo:<\/p>\n<pre><code>import { Component, NgZone } from '@angular\/core';\r\nimport { NavController, AlertController } from 'ionic-angular';\r\nimport { PouchDBProvider } from \"..\/..\/providers\/pouchdb-provider\";\r\nimport * as Uuid from \"uuid\";\r\n\r\n@Component({\r\n    selector: 'page-home',\r\n    templateUrl: 'home.html'\r\n})\r\nexport class HomePage {\r\n\r\n    public items: Array;\r\n\r\n    public constructor(public navCtrl: NavController, public alertCtrl: AlertController, private database: PouchDBProvider, private zone: NgZone) {\r\n        this.items = [];\r\n    }\r\n\r\n    public ionViewDidEnter() { }\r\n\r\n    public insert() { }\r\n\r\n}<\/code><\/pre>\n<p>En el c\u00f3digo anterior estamos importando varios componentes de Ionic y Angular 2, as\u00ed como nuestro proveedor PouchDB y la biblioteca UUID. Muchos de estos componentes se inyectan en el directorio <code>constructor<\/code> m\u00e9todo. En <code>constructor<\/code> tambi\u00e9n inicializa nuestra matriz p\u00fablica que se vincular\u00e1 a la interfaz de usuario. Este array contendr\u00e1 los datos que sincronizamos con PouchDB.<\/p>\n<p>Si bien podemos inicializar nuestras variables en el <code>constructor<\/code> nunca es una buena idea cargar datos en ellos en el m\u00e9todo <code>constructor<\/code> m\u00e9todo. En su lugar debemos utilizar el m\u00e9todo Ionic <code>ionViewDidEnter<\/code> m\u00e9todo:<\/p>\n<pre><code>public ionViewDidEnter() {\r\n    this.database.sync(\"https:\/\/192.168.57.1:4984\/example\");\r\n    this.database.getChangeListener().subscribe(data =&gt; {\r\n        for(let i = 0; i &lt; data.change.docs.length; i++) { this.zone.run(() =&gt; {\r\n                this.items.push(data.change.docs[i]);\r\n            });\r\n        }\r\n    });\r\n    this.database.fetch().then(result =&gt; {\r\n        this.items = [];\r\n        for(let i = 0; i &lt; result.rows.length; i++) { this.items.push(result.rows[i].doc); } }, error =&gt; {\r\n        console.error(error);\r\n    });\r\n}<\/code><\/pre>\n<p>En el <code>ionViewDidEnter<\/code> estamos iniciando la sincronizaci\u00f3n bidireccional con PouchDB y Couchbase Sync Gateway. El nombre de host es el de mi instancia actual de Couchbase Sync Gateway. La base de datos no necesita coincidir con la de mi base de datos local.<\/p>\n<p>Cuando estemos sincronizando tambi\u00e9n vamos a suscribirnos al escuchador de cambios. Esta es una aplicaci\u00f3n simple por lo que no nos preocuparemos de cambiar o borrar datos, s\u00f3lo de a\u00f1adir datos. Los escuchadores pueden ser un poco dudosos en Angular 2 ya que se produce una desconexi\u00f3n entre la interfaz de usuario y los datos. Esta desconexi\u00f3n se puede corregir a\u00f1adiendo los datos del listener en un fichero <code>zona.ejecutar<\/code> m\u00e9todo.<\/p>\n<p>Con la aplicaci\u00f3n suscrita a los cambios, necesitamos hacer una primera consulta de los datos cuando se abra la aplicaci\u00f3n. Queremos <code>buscar<\/code> todos los datos y a\u00f1adirlos a nuestra matriz p\u00fablica.<\/p>\n<p>El \u00faltimo m\u00e9todo que tenemos es el <code>insertar<\/code> y est\u00e1 impulsado principalmente por Ionic:<\/p>\n<pre><code>public insert() {\r\n    let prompt = this.alertCtrl.create({\r\n        title: 'Todo Items',\r\n        message: \"Add a new item to the todo list\",\r\n        inputs: [\r\n            {\r\n                name: 'title',\r\n                placeholder: 'Title'\r\n            },\r\n        ],\r\n        buttons: [\r\n            {\r\n                text: 'Cancel',\r\n                handler: data =&gt; {}\r\n            },\r\n            {\r\n                text: 'Save',\r\n                handler: data =&gt; {\r\n                    this.database.put({type: \"list\", title: data.title}, Uuid.v4());\r\n                }\r\n            }\r\n        ]\r\n    });\r\n    prompt.present();\r\n}<\/code><\/pre>\n<p>Aqu\u00ed creamos una ventana emergente. Cuando se pulsa el bot\u00f3n de guardar, el texto del formulario se guarda con PouchDB. El id del documento se genera un\u00edvocamente con la librer\u00eda UUID.<\/p>\n<p>\u00bfQu\u00e9 aspecto tiene nuestra interfaz de usuario?<\/p>\n<h3 id=\"creating-a-simple-ui-with-html\">Creaci\u00f3n de una interfaz de usuario sencilla con HTML<\/h3>\n<p>La interfaz de usuario es la parte f\u00e1cil porque la aplicaci\u00f3n es muy simplista. Abra el proyecto <strong>src\/pages\/home\/home.html<\/strong> e incluya el siguiente c\u00f3digo HTML:<\/p>\n<pre><code>&lt;ion-header&gt;\r\n    &lt;ion-navbar&gt;\r\n        &lt;ion-title&gt;\r\n            PouchDB w\/ Ionic 2\r\n        &lt;\/ion-title&gt;\r\n        &lt;ion-buttons end&gt;\r\n            &lt;button ion-button icon-only (click)=\"insert()\"&gt;\r\n                &lt;ion-icon name=\"add\"&gt;&lt;\/ion-icon&gt;\r\n            &lt;\/button&gt;\r\n        &lt;\/ion-buttons&gt;\r\n    &lt;\/ion-navbar&gt;\r\n&lt;\/ion-header&gt;\r\n\r\n&lt;ion-content padding&gt;\r\n    &lt;ion-list&gt;\r\n        &lt;ion-item *ngFor=\"let item of items\"&gt;\r\n            {{ item.title }}\r\n        &lt;\/ion-item&gt;\r\n    &lt;\/ion-list&gt;\r\n&lt;\/ion-content&gt;<\/code><\/pre>\n<p>La interfaz de usuario tiene una barra de acci\u00f3n con un bot\u00f3n que, al pulsarlo, activa la funci\u00f3n <code>insertar<\/code> que se encuentra en nuestro TypeScript. El contenido central de la interfaz de usuario es una lista que recorre la matriz p\u00fablica imprimiendo cada elemento en la pantalla.<\/p>\n<h2 id=\"taking-the-project-for-a-test-run\">Prueba del proyecto<\/h2>\n<p>Repasamos muchos conceptos y mucho c\u00f3digo. Para facilitar las cosas, yo <a href=\"https:\/\/github.com\/couchbaselabs\/todolite-ionic2-pouchdb\">cargado un proyecto de trabajo<\/a> a GitHub que puedes descargar y probar por ti mismo.<\/p>\n<p>Con el proyecto descargado, ejecute los siguientes comandos para restaurar las dependencias, plugins y plataformas:<\/p>\n<pre><code>npm install\r\nrestauraci\u00f3n del estado de ionic<\/code><\/pre>\n<p>Siempre y cuando no se olvide de actualizar el <code>sincronizar<\/code> del proyecto <strong>src\/pages\/home\/home.ts<\/strong> con su host Sync Gateway, el proyecto deber\u00eda poder ejecutarse.<\/p>\n<h2 id=\"conclusion\">Conclusi\u00f3n<\/h2>\n<p>Acabas de ver c\u00f3mo crear una aplicaci\u00f3n Android e iOS que se sincroniza usando Ionic 2, PouchDB y Couchbase. Este es un m\u00e9todo alternativo a la <a href=\"https:\/\/www.couchbase.com\/blog\/es\/data-synchronization-with-couchbase-in-ionic-2-hybrid-mobile-apps\/\">gu\u00eda anterior<\/a> que escrib\u00ed que utiliza Couchbase Lite.<\/p>","protected":false},"excerpt":{"rendered":"<p>Not too long ago I wrote about using Couchbase in an Ionic 2 application. In the previous example we saw how to use Couchbase Lite and the RESTful API for saving data and working with Couchbase Sync Gateway. While that [&hellip;]<\/p>","protected":false},"author":63,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,1810,9327],"tags":[1578,1773,1534,1543,1541],"ppma_author":[9032],"class_list":["post-2480","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-couchbase-mobile","category-javascript","tag-angular-2","tag-ionic-2","tag-ionic-framework","tag-javascript","tag-pouchdb"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.5 (Yoast SEO v26.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Syncing with Couchbase in an Ionic 2 App using PouchDB<\/title>\n<meta name=\"description\" content=\"Learn how to create an Android and iOS application that syncs using Ionic 2, PouchDB, and Couchbase. This is an alternative method to Couchbase Lite.\" \/>\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\/es\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Syncing with Couchbase in an Ionic 2 App using PouchDB\" \/>\n<meta property=\"og:description\" content=\"Learn how to create an Android and iOS application that syncs using Ionic 2, PouchDB, and Couchbase. This is an alternative method to Couchbase Lite.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2017-01-01T15:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:15:36+00:00\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Syncing with Couchbase in an Ionic 2 App using PouchDB\",\"datePublished\":\"2017-01-01T15:00:00+00:00\",\"dateModified\":\"2025-06-14T03:15:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\"},\"wordCount\":1680,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"angular 2\",\"ionic 2\",\"ionic framework\",\"javascript\",\"pouchdb\"],\"articleSection\":[\"Best Practices and Tutorials\",\"Couchbase Mobile\",\"JavaScript\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\",\"name\":\"Syncing with Couchbase in an Ionic 2 App using PouchDB\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-01-01T15:00:00+00:00\",\"dateModified\":\"2025-06-14T03:15:36+00:00\",\"description\":\"Learn how to create an Android and iOS application that syncs using Ionic 2, PouchDB, and Couchbase. This is an alternative method to Couchbase Lite.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#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\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Syncing with Couchbase in an Ionic 2 App using PouchDB\"}]},{\"@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\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@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\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Sincronizaci\u00f3n con Couchbase en una app Ionic 2 usando PouchDB","description":"Aprende a crear una aplicaci\u00f3n Android e iOS que se sincroniza usando Ionic 2, PouchDB y Couchbase. Este es un m\u00e9todo alternativo a Couchbase Lite.","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\/es\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/","og_locale":"es_MX","og_type":"article","og_title":"Syncing with Couchbase in an Ionic 2 App using PouchDB","og_description":"Learn how to create an Android and iOS application that syncs using Ionic 2, PouchDB, and Couchbase. This is an alternative method to Couchbase Lite.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2017-01-01T15:00:00+00:00","article_modified_time":"2025-06-14T03:15:36+00:00","author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"8 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Syncing with Couchbase in an Ionic 2 App using PouchDB","datePublished":"2017-01-01T15:00:00+00:00","dateModified":"2025-06-14T03:15:36+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/"},"wordCount":1680,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["angular 2","ionic 2","ionic framework","javascript","pouchdb"],"articleSection":["Best Practices and Tutorials","Couchbase Mobile","JavaScript"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/","url":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/","name":"Sincronizaci\u00f3n con Couchbase en una app Ionic 2 usando PouchDB","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-01-01T15:00:00+00:00","dateModified":"2025-06-14T03:15:36+00:00","description":"Aprende a crear una aplicaci\u00f3n Android e iOS que se sincroniza usando Ionic 2, PouchDB y Couchbase. Este es un m\u00e9todo alternativo a Couchbase Lite.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#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\/syncing-with-couchbase-in-an-ionic-2-app-using-pouchdb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Syncing with Couchbase in an Ionic 2 App using PouchDB"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos 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":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@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\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, Defensor del Desarrollador, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy es un defensor de las tecnolog\u00edas modernas de desarrollo web y m\u00f3vil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y m\u00f3vil m\u00e1s f\u00e1cil de entender.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/es\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","author_category":"","last_name":"Raboy","first_name":"Nic","job_title":"","user_url":"https:\/\/www.thepolyglotdeveloper.com","description":"Nic Raboy es un defensor de las tecnolog\u00edas modernas de desarrollo web y m\u00f3vil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y m\u00f3vil m\u00e1s f\u00e1cil de entender."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/2480","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=2480"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/2480\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=2480"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=2480"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=2480"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=2480"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}