{"id":2096,"date":"2015-11-11T15:00:00","date_gmt":"2015-11-11T15:00:00","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2096"},"modified":"2023-06-27T07:17:25","modified_gmt":"2023-06-27T14:17:25","slug":"cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","title":{"rendered":"Almacenamiento y sincronizaci\u00f3n entre plataformas con Ionic Framework, Couchbase y PouchDB"},"content":{"rendered":"<p>Ionic Framework sigue siendo uno de los l\u00edderes en el desarrollo de aplicaciones m\u00f3viles h\u00edbridas. Permite crear aplicaciones para Android e iOS.<br \/>\nutilizando s\u00f3lo HTML, JavaScript y CSS.<\/p>\n<p>Anteriormente escrib\u00ed sobre c\u00f3mo utilizar <a href=\"https:\/\/www.couchbase.com\/blog\/es\/using-couchbase-in-your-ionic-framework-application-part-1\/\">Couchbase en<br \/>\nuna aplicaci\u00f3n m\u00f3vil Android e iOS con Ionic Framework<\/a>pero hac\u00eda uso de Couchbase<br \/>\nLite como su base de datos NoSQL integrada. En esta ocasi\u00f3n vamos a ver c\u00f3mo sustituir Couchbase Lite por PouchDB. \u00bfDeber\u00edas usar una<br \/>\nm\u00e9todo sobre el otro? No, al final todo se reduce a preferencias.<\/p>\n<p>Si todav\u00eda no ha visto mi post sobre <a href=\"https:\/\/www.couchbase.com\/blog\/es\/sync-with-couchbase-using-only-angularjs-and-pouchdb\/\">PouchDB<br \/>\ny AngularJS con Couchbase<\/a>Si est\u00e1s interesado, te animo a que le eches un vistazo, ya que este tutorial utilizar\u00e1 muchos de los mismos conceptos y c\u00f3digo.<\/p>\n<h2>Qu\u00e9 necesitaremos<\/h2>\n<p>Hay algunos requisitos para la aplicaci\u00f3n que vamos a construir. Veremos c\u00f3mo obtenerlos a lo largo del camino, pero aqu\u00ed hay un<br \/>\nsabor para que sepas en qu\u00e9 te est\u00e1s metiendo.<\/p>\n<ul>\n<li>Pasarela de sincronizaci\u00f3n Couchbase<\/li>\n<li>PouchDB 4<\/li>\n<li>Marco i\u00f3nico 1<\/li>\n<\/ul>\n<h3>Obtenci\u00f3n de la puerta de enlace Couchbase Sync<\/h3>\n<p>Este proyecto requerir\u00e1 Couchbase Sync Gateway para tener \u00e9xito. Si no est\u00e1s familiarizado, el Couchbase Sync Gateway es un<br \/>\nque se encarga de procesar los datos entre la aplicaci\u00f3n local (tu aplicaci\u00f3n Ionic Framework) y el servidor Couchbase. Nosotros<br \/>\nno utilizaremos Couchbase Server en este ejemplo, por lo que Sync Gateway actuar\u00e1 como nuestra soluci\u00f3n de almacenamiento en memoria en la nube.<\/p>\n<p>La puerta de enlace de sincronizaci\u00f3n de Couchbase se encuentra en la direcci\u00f3n <a href=\"https:\/\/www.couchbase.com\/blog\/es\/nosql-databases\/downloads\/\">Secci\u00f3n de descargas de Couchbase<\/a>.<\/p>\n<h2>Creaci\u00f3n de nuestro proyecto Ionic Framework<\/h2>\n<p>Antes de seguir adelante es bueno tener en cuenta que si usted no est\u00e1 usando un Mac, no se puede a\u00f1adir y construir para la plataforma iOS. Windows, Mac,<br \/>\ny Linux pueden construir para Android, pero s\u00f3lo Mac puede construir para iOS.<\/p>\n<p>Desde el s\u00edmbolo del sistema (Windows) o Terminal (Mac y Linux), ejecute el siguiente comando para crear un nuevo proyecto de Ionic Framework:<\/p>\n<pre><code class=\"language-bash\">\r\nionic start PouchProject en blanco\r\ncd PouchProject\r\nplataforma ionic a\u00f1adir android\r\nplataforma ionic add ios\r\n<\/code><\/pre>\n<p>Nuestro proyecto de plantilla en blanco ya est\u00e1 listo para trabajar con \u00e9l.<\/p>\n<h3>Incluir las dependencias<\/h3>\n<p>Si a\u00fan no lo has hecho, <a href=\"https:\/\/www.pouchdb.com\/\">descargar PouchDB 4<\/a> y tome nota de la <strong>min.js<\/strong> archivo como<br \/>\nque utilizaremos en el proyecto. Copia el<br \/>\nPouchDB <strong>min.js<\/strong> en el archivo <strong>www\/js<\/strong> directorio.<\/p>\n<p>Con el archivo en su sitio, abra el archivo <strong>www\/index.html<\/strong> e incluya lo siguiente:<\/p>\n<pre><code class=\"language-html\">\r\n\r\n<\/code><\/pre>\n<p>Esta l\u00ednea de script debe aparecer encima de <strong>app.js<\/strong> y la informaci\u00f3n de la versi\u00f3n debe coincidir con la de su actual<br \/>\nen lugar de la versi\u00f3n que he incluido aqu\u00ed.<\/p>\n<h3>Modificaci\u00f3n del fichero \u00edndice<\/h3>\n<p>Antes de pasar al c\u00f3digo de AngularJS, tenemos que hacer una revisi\u00f3n final del proyecto <strong>www\/index.html<\/strong> archivo. \u00c1bralo y<br \/>\nsustituye las etiquetas por lo siguiente:<\/p>\n<pre><code class=\"language-html\">\r\n\r\n    \r\n        \r\n        \r\n    \r\n\r\n<\/code><\/pre>\n<p>Dado que estamos utilizando el UI-Router de AngularJS que se incluye con Ionic Framework, s\u00f3lo necesitamos una aplicaci\u00f3n b\u00e1sica <strong>www\/index.html<\/strong> archivo.<\/p>\n<h3>Creaci\u00f3n de nuestro servicio PouchDB AngularJS<\/h3>\n<p>Antes de empezar a utilizar PouchDB, tenemos que hacer una envoltura para que se ajuste bien con AngularJS y Ionic Framework. Fuera de la caja PouchDB<br \/>\nes una biblioteca JavaScript de vainilla, por lo que no es necesariamente la m\u00e1s f\u00e1cil de usar cuando se trata de AngularJS.<\/p>\n<p>Dentro de la secci\u00f3n <strong>www\/js\/app.js<\/strong> incluya el siguiente c\u00f3digo de servicio:<\/p>\n<pre><code class=\"language-javascript\">\r\n.service(\"$pouchDB\", [\"$rootScope\", \"$q\", function($rootScope, $q) {\r\n\r\n    var database;\r\n    var changeListener;\r\n\r\n    this.setDatabase = function(databaseName) {\r\n        database = new PouchDB(databaseName);\r\n    }\r\n\r\n    this.startListening = function() {\r\n        changeListener = database.changes({\r\n            live: true,\r\n            include_docs: true\r\n        }).on(\"change\", function(change) {\r\n            if(!change.deleted) {\r\n                $rootScope.$broadcast(\"$pouchDB:change\", change);\r\n            } else {\r\n                $rootScope.$broadcast(\"$pouchDB:delete\", change);\r\n            }\r\n        });\r\n    }\r\n\r\n    this.stopListening = function() {\r\n        changeListener.cancel();\r\n    }\r\n\r\n    this.sync = function(remoteDatabase) {\r\n        database.sync(remoteDatabase, {live: true, retry: true});\r\n    }\r\n\r\n    this.save = function(jsonDocument) {\r\n        var deferred = $q.defer();\r\n        if(!jsonDocument._id) {\r\n            database.post(jsonDocument).then(function(response) {\r\n                deferred.resolve(response);\r\n            }).catch(function(error) {\r\n                deferred.reject(error);\r\n            });\r\n        } else {\r\n            database.put(jsonDocument).then(function(response) {\r\n                deferred.resolve(response);\r\n            }).catch(function(error) {\r\n                deferred.reject(error);\r\n            });\r\n        }\r\n        return deferred.promise;\r\n    }\r\n\r\n    this.delete = function(documentId, documentRevision) {\r\n        return database.remove(documentId, documentRevision);\r\n    }\r\n\r\n    this.get = function(documentId) {\r\n        return database.get(documentId);\r\n    }\r\n\r\n    this.destroy = function() {\r\n        database.destroy();\r\n    }\r\n\r\n}])\r\n<\/code><\/pre>\n<p>Puede que ese c\u00f3digo te resulte familiar. Pues bien, es el c\u00f3digo exacto que utilic\u00e9 en<br \/>\nel <a href=\"https:\/\/www.couchbase.com\/blog\/es\/sync-with-couchbase-using-only-angularjs-and-pouchdb\/\">ejemplo anterior de PouchDB para AngularJS<\/a>.<br \/>\nAhora podemos utilizar f\u00e1cilmente PouchDB en nuestro proyecto.<\/p>\n<h3>Crear una base de datos local e iniciar la sincronizaci\u00f3n<\/h3>\n<p>El objetivo aqu\u00ed es crear una base de datos local cuando nuestra aplicaci\u00f3n se inicia (si no existe ya) y luego comenzar a sincronizar con el<br \/>\nCouchbase Sync Gateway. Esto se puede lograr en el AngularJS <strong>ejecutar()<\/strong> funci\u00f3n de nuestro <strong>www\/js\/app.js<\/strong><br \/>\nfile:<\/p>\n<pre><code class=\"language-javascript\">\r\n.run(function($ionicPlatform, $pouchDB) {\r\n    $ionicPlatform.ready(function() {\r\n        if(window.cordova &amp;&amp; window.cordova.plugins.Keyboard) {\r\n            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);\r\n        }\r\n        if(window.StatusBar) {\r\n            StatusBar.styleDefault();\r\n        }\r\n    });\r\n    $pouchDB.setDatabase(\"nraboy-test\");\r\n    if(ionic.Platform.isAndroid()) {\r\n        $pouchDB.sync(\"https:\/\/192.168.57.1:4984\/test-database\");\r\n    } else {\r\n        $pouchDB.sync(\"https:\/\/localhost:4984\/test-database\");\r\n    }\r\n})\r\n<\/code><\/pre>\n<p>Las direcciones IP que he utilizado pueden variar para usted en t\u00e9rminos de simuladores, pero para la producci\u00f3n es probable que coincida tanto para iOS y<br \/>\nAndroid.<\/p>\n<h3>Dise\u00f1o de un controlador para sus vistas<\/h3>\n<p>Todav\u00eda no hemos creado nuestras vistas, pero vamos a seguir adelante y crear la l\u00f3gica del controlador para ellos. Abre el archivo<br \/>\n<strong>www\/js\/app.js<\/strong> e incluya el siguiente controlador:<\/p>\n<pre><code class=\"language-javascript\">\r\n.controller(\"MainController\", function($scope, $rootScope, $state, $stateParams, $ionicHistory, $pouchDB) {\r\n\r\n    $scope.items = {};\r\n\r\n    $scope.save = function(firstname, lastname, email) { }\r\n\r\n    $scope.delete = function(id, rev) { }\r\n\r\n    $scope.back = function() { }\r\n\r\n})\r\n<\/code><\/pre>\n<p>En este momento tenemos un controlador b\u00e1sico. Sabemos que vamos a guardar y eliminar elementos, por lo que hemos definido una funci\u00f3n para ello<br \/>\ntareas. Tambi\u00e9n tenemos una funci\u00f3n llamada <strong>atr\u00e1s()<\/strong> que har\u00e1 aparecer un elemento (retroceder) en la pila del historial.<\/p>\n<p>Vayamos de abajo arriba y empecemos por el <strong>atr\u00e1s()<\/strong> funci\u00f3n. Debe contener el siguiente c\u00f3digo:<\/p>\n<pre><code class=\"language-javascript\">\r\n$scope.back = function() {\r\n    $ionicHistory.goBack();\r\n}\r\n<\/code><\/pre>\n<p>Cuando se trata de eliminar elementos de la base de datos, tendremos que proporcionar un identificador de documento concreto para eliminar, as\u00ed como la revisi\u00f3n concreta<br \/>\nque deseamos eliminar. Todo esto se pasar\u00e1 desde las vistas, pero la l\u00f3gica ser\u00e1 la siguiente:<\/p>\n<pre><code class=\"language-javascript\">\r\n$scope.delete = function(id, rev) {\r\n    $pouchDB.delete(id, rev);\r\n}\r\n<\/code><\/pre>\n<p>En <strong>suprimir(id, rev)<\/strong> hace una llamada al servicio PouchDB que hemos creado.<\/p>\n<p>Esto nos deja con la <strong>guardar()<\/strong> funci\u00f3n. Bas\u00e1ndonos en la simplicidad de nuestra aplicaci\u00f3n s\u00f3lo guardaremos tres datos<br \/>\npero puede cambiarse f\u00e1cilmente si es necesario. Dentro de su controlador, haga que el <strong>guardar()<\/strong> as\u00ed:<\/p>\n<pre><code class=\"language-javascript\">\r\n$scope.save = function(firstname, lastname, email) {\r\n    var jsonDocument = {\r\n        \"firstname\": firstname,\r\n        \"lastname\": lastname,\r\n        \"email\": email\r\n    };\r\n    if($stateParams.documentId) {\r\n        jsonDocument[\"_id\"] = $stateParams.documentId;\r\n        jsonDocument[\"_rev\"] = $stateParams.documentRevision;\r\n    }\r\n    $pouchDB.save(jsonDocument).then(function(response) {\r\n        $state.go(\"list\");\r\n    }, function(error) {\r\n        console.log(\"ERROR -&gt; \" + error);\r\n    });\r\n}\r\n<\/code><\/pre>\n<p>Esta funci\u00f3n hace dos cosas. Preparar\u00e1 una inserci\u00f3n o preparar\u00e1 una actualizaci\u00f3n en caso de que un id de documento y una revisi\u00f3n de documento<br \/>\nestar disponible.<\/p>\n<p>Pero a\u00fan no hemos terminado. Aunque hemos terminado todas nuestras funciones, todav\u00eda tenemos que manejar la escucha de<br \/>\ncambios. Cuando llamamos a <strong>$pouchDB.startListening();<\/strong> en nuestro controlador, nuestro servicio PouchDB empezar\u00e1 a hacer uso de la funci\u00f3n<br \/>\nAngularJS <strong>$ransmisi\u00f3n<\/strong>. Mientras est\u00e1 emitiendo podemos escuchar esas emisiones usando algo como:<\/p>\n<pre><code class=\"language-javascript\">\r\n$rootScope.$on(\"$pouchDB:change\", function(event, data) {\r\n    $scope.items[data.doc._id] = data.doc;\r\n    $scope.$apply();\r\n});\r\n\r\n$rootScope.$on(\"$pouchDB:delete\", function(event, data) {\r\n    delete $scope.items[data.doc._id];\r\n    $scope.$apply();\r\n});\r\n<\/code><\/pre>\n<p>La l\u00f3gica de nuestro controlador de vista ya est\u00e1 lista.<\/p>\n<h3>Definici\u00f3n de las vistas de Ionic Framework<\/h3>\n<p>La \u00faltima parte de nuestro <strong>www\/js\/app.js<\/strong> ser\u00e1 para definir nuestras vistas. Esto se hace en el archivo AngularJS<br \/>\n<strong>configurar()<\/strong> as\u00ed:<\/p>\n<pre><code class=\"language-javascript\">\r\n.config(function($stateProvider, $urlRouterProvider) {\r\n    $stateProvider\r\n        .state(\"list\", {\r\n            \"url\": \"\/list\",\r\n            \"templateUrl\": \"templates\/list.html\",\r\n            \"controller\": \"MainController\"\r\n        })\r\n        .state(\"item\", {\r\n            \"url\": \"\/item\/:documentId\/:documentRevision\",\r\n            \"templateUrl\": \"templates\/item.html\",\r\n            \"controller\": \"MainController\"\r\n        });\r\n    $urlRouterProvider.otherwise(\"list\");\r\n})\r\n<\/code><\/pre>\n<p>Definimos dos vistas, una para todos los elementos de nuestra lista y otra para crear y actualizar nuevos elementos de la lista. El sitio <strong>art\u00edculo<\/strong> toma un valor opcional<br \/>\nid del documento y revisi\u00f3n del documento. Cuando est\u00e1n presentes, significa que vamos a actualizar un documento en particular.<\/p>\n<p>Toda nuestra l\u00f3gica AngularJS est\u00e1 completa ahora. Hemos inicializado nuestra base de datos, iniciado la sincronizaci\u00f3n, definido nuestras vistas y planificado la interacci\u00f3n<br \/>\nde nuestros puntos de vista.<\/p>\n<h4>Creaci\u00f3n de una vista de lista<\/h4>\n<p>Aqu\u00ed definiremos c\u00f3mo se presentan los datos en la lista. En la secci\u00f3n <strong>www\/plantillas\/lista.html<\/strong> a\u00f1ada el siguiente c\u00f3digo:<\/p>\n<pre><code class=\"language-html\">\r\n\r\n    \r\n        <button class=\"right button button-icon icon ion-plus\"><\/button>\r\n    \r\n    \r\n        \r\n            \r\n                {{value.firstname}} {{value.lastname}}\r\n                \r\n            \r\n        \r\n    \r\n\r\n<\/code><\/pre>\n<p>Al deslizar un elemento de la lista se nos presenta un bot\u00f3n de borrado que llamar\u00e1 a la funci\u00f3n <strong>suprimir()<\/strong> de nuestro controlador.<\/p>\n<h4>Creaci\u00f3n de una vista de formulario<\/h4>\n<p>Aqu\u00ed definiremos los documentos que ser\u00e1n insertados o actualizados en nuestra base de datos. Esencialmente, esta vista es s\u00f3lo un formulario. En su proyecto<br \/>\n<strong>www\/templates\/item.html<\/strong> a\u00f1ada el siguiente c\u00f3digo:<\/p>\n<div class=\"list\"><label class=\"item item-input\">  <\/label> <label class=\"item item-input\">  <\/label> <label class=\"item item-input\">  <\/label><\/div>\n<p>&nbsp;<\/p>\n<div class=\"padding\"><button class=\"button button-block button-positive\"> Guardar <\/button><\/div>\n<h2>Configuraci\u00f3n de la pasarela de sincronizaci\u00f3n<\/h2>\n<p>PouchDB y Ionic Framework son s\u00f3lo la mitad de la historia aqu\u00ed. Claro que van a crear una buena aplicaci\u00f3n de ejecuci\u00f3n local, pero queremos que las cosas se sincronicen. El Couchbase Sync Gateway es nuestro punto final para esto y por supuesto PouchDB funciona muy bien con \u00e9l.<\/p>\n<p>Dentro de la secci\u00f3n <strong>sync-gateway-config.json<\/strong> a\u00f1ada lo siguiente:<\/p>\n<pre><code class=\"language-json\">\r\n{\r\n    \"log\":[\"CRUD+\", \"REST+\", \"Changes+\", \"Attach+\"],\r\n    \"databases\": {\r\n        \"test-database\": {\r\n            \"server\":\"walrus:data\",\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:9000\"],\r\n        \"LoginOrigin\": [\"https:\/\/localhost:9000\"],\r\n        \"Headers\": [\"Content-Type\"],\r\n        \"MaxAge\": 17280000\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>Esta es una de las configuraciones m\u00e1s b\u00e1sicas que existen. Algunas cosas a tener en cuenta al respecto:<\/p>\n<ul>\n<li>Utiliza walrus:data para el almacenamiento, que est\u00e1 en memoria y no persiste. No debe utilizarse para producci\u00f3n.<\/li>\n<li>Todos los datos se sincronizan a trav\u00e9s del usuario GUEST, por lo que no hay autenticaci\u00f3n aqu\u00ed, pero podr\u00eda haberla.<\/li>\n<li>Estamos arreglando los problemas de CORS permitiendo peticiones en localhost:9000 en caso de que quieras servir con Python para pruebas de navegador.<\/li>\n<\/ul>\n<h2>Probar la aplicaci\u00f3n<\/h2>\n<p>En este punto todo nuestro c\u00f3digo est\u00e1 en su lugar y nuestro Sync Gateway est\u00e1 listo para ser ejecutado. Inicie el Sync Gateway ejecutando lo siguiente en un archivo<br \/>\nS\u00edmbolo del sistema o Terminal:<\/p>\n<pre><code class=\"language-bash\">\r\n\/ruta\/a\/sync\/gateway\/bin\/sync-gateway \/ruta\/a\/proyecto\/sync-gateway-config.json\r\n<\/code><\/pre>\n<p>La puerta de enlace de sincronizaci\u00f3n deber\u00eda estar ahora en funcionamiento y puede validarlo visitando https:\/\/localhost:4984 en su navegador web.<\/p>\n<h3>Pruebas para Android<\/h3>\n<p>Con un dispositivo conectado o un simulador en ejecuci\u00f3n, desde el s\u00edmbolo del sistema o el terminal, ejecute los dos comandos siguientes para crear y<br \/>\ninstalar el archivo APK:<\/p>\n<pre><code class=\"language-bash\">\r\nionic build android\r\nadb install -r platforms\/android\/build\/outputs\/apk\/android-debug.apk\r\n<\/code><\/pre>\n<h3>Pruebas para iOS<\/h3>\n<p>Hay dos buenas maneras de hacer esto. Usted puede construir el proyecto y abrirlo con Xcode, o puede construir y<br \/>\nemular la aplicaci\u00f3n sin lanzar Xcode. El primero se puede hacer as\u00ed:<\/p>\n<pre><code class=\"language-bash\">\r\nionic build ios\r\n<\/code><\/pre>\n<p>A continuaci\u00f3n, abra el directorio platform\/ios\/ del proyecto e inicie el archivo de proyecto de Xcode.<\/p>\n<p>Si has instalado el paquete ios-sim de Node Package Manager (NPM), puedes hacer lo siguiente:<\/p>\n<pre><code class=\"language-bash\">\r\nionic build ios\r\nionic emulate ios\r\n<\/code><\/pre>\n<h2>Conclusi\u00f3n<\/h2>\n<p>Ya has visto que hay dos formas de utilizar Couchbase en tu aplicaci\u00f3n m\u00f3vil Android e iOS de Ionic Framework. Puedes utilizar el<br \/>\nApache Cordova Couchbase plugin como se demuestra en<br \/>\nel <a href=\"https:\/\/www.couchbase.com\/blog\/es\/using-couchbase-in-your-ionic-framework-application-part-1\/\">series de blogs anteriores<\/a>o puede<br \/>\nutilizar PouchDB. Ambos son opciones muy adecuadas cuando se trata de almacenamiento y sincronizaci\u00f3n de datos entre plataformas en tu aplicaci\u00f3n.<\/p>\n<p>Puede obtener el c\u00f3digo fuente completo de esta entrada de blog a trav\u00e9s de<br \/>\nnuestra <a href=\"https:\/\/github.com\/couchbaselabs\/ionic-framework-pouchdb\">Repositorio GitHub de Couchbase Labs<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework [&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":[1],"tags":[1542,1551,1534,1541],"ppma_author":[9032],"class_list":["post-2096","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-angularjs","tag-hybrid","tag-ionic-framework","tag-pouchdb"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Sync Couchbase in Ionic Framework and PouchDB<\/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\/es\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB\" \/>\n<meta property=\"og:description\" content=\"Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-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=\"2015-11-11T15:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-06-27T14:17:25+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\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB\",\"datePublished\":\"2015-11-11T15:00:00+00:00\",\"dateModified\":\"2023-06-27T14:17:25+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\"},\"wordCount\":1503,\"commentCount\":28,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"angularjs\",\"hybrid\",\"ionic framework\",\"pouchdb\"],\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\",\"name\":\"Sync Couchbase in Ionic Framework and PouchDB\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2015-11-11T15:00:00+00:00\",\"dateModified\":\"2023-06-27T14:17:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-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\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and 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":"Sync Couchbase in Ionic Framework and PouchDB","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\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","og_locale":"es_MX","og_type":"article","og_title":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB","og_description":"Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/es\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2015-11-11T15:00:00+00:00","article_modified_time":"2023-06-27T14:17:25+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\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB","datePublished":"2015-11-11T15:00:00+00:00","dateModified":"2023-06-27T14:17:25+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"},"wordCount":1503,"commentCount":28,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["angularjs","hybrid","ionic framework","pouchdb"],"articleSection":["Uncategorized"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","url":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","name":"Sync Couchbase in Ionic Framework and PouchDB","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2015-11-11T15:00:00+00:00","dateModified":"2023-06-27T14:17:25+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-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\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and 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\/2096","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=2096"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/2096\/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=2096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=2096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=2096"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=2096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}