{"id":4542,"date":"2018-02-08T07:00:16","date_gmt":"2018-02-08T15:00:16","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4542"},"modified":"2025-06-13T18:45:48","modified_gmt":"2025-06-14T01:45:48","slug":"use-openwhisk-for-faas-with-node-js-and-couchbase-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","title":{"rendered":"Utilizar OpenWhisk para FaaS con Node.js y Couchbase NoSQL"},"content":{"rendered":"<p>Si has estado al d\u00eda con mi contenido, recordar\u00e1s que hab\u00eda escrito un art\u00edculo titulado,\u00a0<a href=\"https:\/\/www.couchbase.com\/blog\/es\/use-aws-lambda-api-gateway-node-js-couchbase-nosql\/\" target=\"_blank\" rel=\"noopener\">Utilizar AWS Lambda y API Gateway con Node.js y Couchbase NoSQL<\/a>. En este art\u00edculo hab\u00edamos explorado el uso de los servicios Serverless de Amazon para crear funciones Lambda que interact\u00faan con Couchbase, nuestra base de datos NoSQL.<\/p>\n<p>Sin embargo, Lambda no es la \u00fanica tecnolog\u00eda sin servidor, tambi\u00e9n conocida como funciones como servicio (FaaS). Por ejemplo, <a href=\"https:\/\/openwhisk.apache.org\/\" target=\"_blank\" rel=\"noopener\">Apache OpenWhisk<\/a> por ejemplo. Con OpenWhisk puede crear funciones de forma similar a como lo har\u00eda con Lambda, pero desplegarlas en un conjunto m\u00e1s diverso de ubicaciones, siendo la m\u00e1s popular IBM Bluemix.<\/p>\n<p>Vamos a ver c\u00f3mo crear funciones sin servidor utilizando OpenWhisk para comunicarnos con nuestro <a href=\"https:\/\/www.couchbase.com\/blog\/es\/\" target=\"_blank\" rel=\"noopener\">Servidor Couchbase<\/a> base de datos.<\/p>\n<p><!--more--><\/p>\n<p>De cara al futuro, hay algunas cosas a tener en cuenta. Necesitar\u00e1s alojar Couchbase Server en alg\u00fan lugar accesible por el mundo exterior. Esto significa que tu ordenador local no funcionar\u00e1. Vas a necesitar Docker para que podamos compilar nuestras dependencias para trabajar con OpenWhisk. Por \u00faltimo, vas a necesitar una cuenta Bluemix, al menos para este ejemplo.<\/p>\n<h2>Instalaci\u00f3n de las herramientas CLI de Bluemix para OpenWhisk<\/h2>\n<p>Como he mencionado anteriormente, OpenWhisk es un proyecto de la Fundaci\u00f3n Apache. Sin embargo, por comodidad vamos a utilizarlo en IBM Bluemix.<\/p>\n<p>Crear una cuenta para el <a href=\"https:\/\/console.bluemix.net\/openwhisk\/\" target=\"_blank\" rel=\"noopener\">Nube de IBM<\/a> si a\u00fan no lo ha hecho.<\/p>\n<p>En lugar de utilizar una herramienta framework como Serverless, vamos a utilizar la CLI de Bluemix. Descarga el <a href=\"https:\/\/console.bluemix.net\/openwhisk\/learn\/cli\" target=\"_blank\" rel=\"noopener\">CLI de IBM Cloud Functions<\/a> para que podamos interactuar con OpenWhisk en IBM.<\/p>\n<p>Antes de empezar a trabajar con su cuenta de IBM Cloud, debe iniciar sesi\u00f3n a trav\u00e9s de la CLI. Desde la l\u00ednea de comandos, ejecute lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">bx login -a api.ng.bluemix.net -o your_email@example.com -s dev<\/pre>\n<p>Al descargar la CLI, se le dar\u00e1 el comando exacto, pero debe ser similar a lo que he presentado anteriormente.<\/p>\n<p>Ahora podemos empezar a crear nuestro proyecto.<\/p>\n<h2>Comprender la estructura del proyecto y el proceso de creaci\u00f3n de paquetes OpenWhisk<\/h2>\n<p>Si nunca has trabajado con FaaS antes, las cosas se hacen un poco diferente a la construcci\u00f3n de una aplicaci\u00f3n independiente, dif\u00edcilmente escalable.<\/p>\n<p>Por ejemplo, cada punto final en nuestro proyecto FaaS ser\u00e1 una funci\u00f3n separada. Combinadas, estas funciones crean lo que se denomina un paquete. Estas funciones se escalan seg\u00fan sea necesario para satisfacer la demanda cambiante de su aplicaci\u00f3n.<\/p>\n<p>Dicho esto, crea lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">crear\r\n--- paquete.json\r\n--- crear.js\r\nrecuperar\r\n--- paquete.json\r\n--- recuperar.js\r\nactualizar\r\n--- paquete.json\r\n--- actualizar.js\r\nborrar\r\n--- paquete.json\r\n--- delete.js<\/pre>\n<p>El proyecto debe tener un directorio para cada funci\u00f3n que deseemos crear. Cada funci\u00f3n tendr\u00e1 su propio directorio\u00a0<strong>paquete.json<\/strong> archivo. Cada\u00a0<strong>paquete.json<\/strong> se puede crear ejecutando lo siguiente dentro de cada uno de los directorios:<\/p>\n<pre class=\"lang:default decode:true\">npm init -y<\/pre>\n<p>Dentro de cada uno de los\u00a0<strong>paquete.json<\/strong> tambi\u00e9n tendr\u00e1 que definir qu\u00e9 archivo es el c\u00f3digo de su funci\u00f3n. Por ejemplo, abra\u00a0<strong>crear\/paquete.json<\/strong> y a\u00f1ada o cambie la siguiente l\u00ednea:<\/p>\n<pre class=\"lang:default decode:true\">\"main\": \"create.js\",<\/pre>\n<p>Al fijar el <code>principal<\/code> estamos indicando qu\u00e9 archivo JavaScript contiene nuestra funci\u00f3n.<\/p>\n<p>Cuando empecemos a desplegar nuestras funciones, lo haremos para que formen parte del mismo paquete.<\/p>\n<h2>Dise\u00f1ar una funci\u00f3n para crear datos<\/h2>\n<p>Comencemos el desarrollo con la creaci\u00f3n de datos en nuestra base de datos. Navega a la base de datos\u00a0<strong>crear<\/strong> y ejecute el siguiente comando desde la l\u00ednea de comandos:<\/p>\n<pre class=\"lang:default decode:true\">npm install couchbase uuid joi --save<\/pre>\n<p>El comando anterior instalar\u00e1 nuestras dependencias de funciones. Usaremos el SDK de Couchbase para Node.js, la librer\u00eda UUID para generar claves \u00fanicas, y la librer\u00eda Joi para validar la entrada.<\/p>\n<p>Volveremos a revisar la instalaci\u00f3n de la dependencia, pero al menos nos mantendr\u00e1 en marcha por ahora.<\/p>\n<p>Ahora abra el proyecto\u00a0<strong>crear\/create.js<\/strong> e incluya lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">const Couchbase = require(\"couchbase\");\r\nconst UUID = require(\"uuid\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        firstname: Joi.string().required(),\r\n        lastname: Joi.string().required(),\r\n        type: Joi.string().forbidden().default(\"person\")\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        var id = UUID.v4();\r\n        bucket.insert(id, validation.value, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            data.id = id;\r\n            response = {\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>El c\u00f3digo anterior es un poco demasiado, as\u00ed que tenemos que averiguar lo que est\u00e1 pasando. Vamos a empezar con la variable que existe fuera de nuestra funci\u00f3n:<\/p>\n<pre class=\"lang:default decode:true\">var bucket = null;<\/pre>\n<p>No es la mejor idea establecer una nueva conexi\u00f3n cada vez que se llama a la funci\u00f3n. En su lugar, podemos mantener una instancia global del Couchbase Bucket abierto y mientras exista, usarlo. S\u00f3lo ten en cuenta que no siempre existir\u00e1 porque OpenWhisk destruir\u00e1 las funciones despu\u00e9s de un tiempo de inactividad.<\/p>\n<pre class=\"lang:default decode:true\">if(bucket == null) {\r\n    var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n    cluster.authenticate(params.username, params.password);\r\n    bucket = cluster.openBucket(params.bucketName);\r\n}<\/pre>\n<p>Dentro de nuestra funci\u00f3n comprobamos si el Bucket ya est\u00e1 abierto. Si el Bucket no est\u00e1 abierto, establecemos una conexi\u00f3n utilizando los par\u00e1metros pasados a la funci\u00f3n. Cuando llegue el momento, definiremos par\u00e1metros por defecto que contengan esta informaci\u00f3n de conexi\u00f3n.<\/p>\n<p>Como estamos creando datos, necesitamos validar que la entrada es correcta.<\/p>\n<pre class=\"lang:default decode:true\">var schema = Joi.object().keys({\r\n    nombre: Joi.string().required(),\r\n    apellido: Joi.string().required(),\r\n    tipo: Joi.string().forbidden().default(\"persona\")\r\n});<\/pre>\n<p>Esperamos un <code>nombre<\/code> y <code>apellido<\/code> est\u00e9 presente. Tambi\u00e9n esperamos un <code>tipo<\/code> no est\u00e9 presente. Podemos validar esto con lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">var validation = Joi.validate(data, schema, { stripUnknown: true });\r\nif(validaci\u00f3n.error) {\r\n    respuesta = {\r\n        statusCode: 500,\r\n        body: JSON.stringify(validaci\u00f3n.error.detalles)\r\n    };\r\n    reject(response);\r\n}<\/pre>\n<p>En <code>stripUnknown<\/code> eliminar\u00e1 los datos no definidos en el esquema. Necesitamos eliminar datos porque nuestra informaci\u00f3n de entrada y de conexi\u00f3n existir\u00e1 en la misma carga \u00fatil. No queremos que la informaci\u00f3n de conexi\u00f3n se guarde en nuestros documentos. Si hay un error de validaci\u00f3n, ser\u00e1 devuelto. Si no hubo error de validaci\u00f3n, podemos proceder a insertar los datos.<\/p>\n<pre class=\"lang:default decode:true\">var id = UUID.v4();\r\nbucket.insert(id, validation.value, (error, result) =&gt; {\r\n    if(error) {\r\n        respuesta = {\r\n            cuerpo: JSON.stringify({\r\n                c\u00f3digo: error.code\r\n                mensaje: error.mensaje\r\n            })\r\n        };\r\n        reject(respuesta);\r\n    }\r\n    data.id = id;\r\n    respuesta = {\r\n        cuerpo: JSON.stringify(validaci\u00f3n.valor)\r\n    };\r\n    resolver(respuesta);\r\n});<\/pre>\n<p>Podemos generar una nueva clave \u00fanica y guardar los datos validados como un documento. Los propios datos se devolver\u00e1n como respuesta.<\/p>\n<p>Las dem\u00e1s funciones seguir\u00e1n esta misma estrategia, m\u00e1s o menos.<\/p>\n<h2>Dise\u00f1o de una Funci\u00f3n para Recuperar Datos con N1QL<\/h2>\n<p>Ahora que tenemos los datos, vamos a intentar recuperarlos de la base de datos con una invocaci\u00f3n a una funci\u00f3n. Navega a tu\u00a0<strong>recuperar<\/strong> y ejecute lo siguiente desde la l\u00ednea de comandos:<\/p>\n<pre class=\"lang:default decode:true\">npm install couchbase --save<\/pre>\n<p>Como no vamos a crear datos, no necesitamos generar valores \u00fanicos ni validar ning\u00fan dato de usuario. Por esta raz\u00f3n, s\u00f3lo necesitamos el SDK de Couchbase para esta funci\u00f3n.<\/p>\n<p>Abra el archivo\u00a0<strong>recuperar\/retrieve.js<\/strong> e incluya lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">const Couchbase = require(\"couchbase\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var response = {};\r\n    var statement = \"SELECT META().id, `\" + bucket._name + \"`.* FROM `\" + bucket._name + \"` WHERE type = 'person'\";\r\n    var query = Couchbase.N1qlQuery.fromString(statement);\r\n    return new Promise((resolve, reject) =&gt; {\r\n        bucket.query(query, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                body: JSON.stringify(result)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>Vamos a saltar sobre lo que ya hemos visto en la funci\u00f3n anterior y saltar a lo que es nuevo. Una vez que estamos conectados a un Bucket abierto, podemos crear una consulta N1QL.<\/p>\n<pre class=\"lang:default decode:true\">var statement = \"SELECT META().id, `\" + bucket._name + \"`.* FROM `\" + bucket._name + \"` WHERE type = 'person'\";\r\nvar query = Couchbase.N1qlQuery.fromString(statement);\r\nreturn new Promise((resolve, reject) =&gt; {\r\n    bucket.query(query, (error, result) =&gt; {\r\n        if(error) {\r\n            respuesta = {\r\n                cuerpo: JSON.stringify({\r\n                    c\u00f3digo: error.code\r\n                    mensaje: error.mensaje\r\n                })\r\n            };\r\n            reject(respuesta);\r\n        }\r\n        respuesta = {\r\n            cuerpo: JSON.stringify(resultado)\r\n        };\r\n        resolver(respuesta);\r\n    });\r\n});<\/pre>\n<p>Esta consulta N1QL es de tipo SQL y nos permitir\u00e1 recuperar todos los documentos que coincidan con ciertos criterios. Si hay alg\u00fan error, lo devuelve como respuesta, en caso contrario devuelve el conjunto de resultados.<\/p>\n<p>Como no estamos validando nada, esta funci\u00f3n para recuperar datos era mucho m\u00e1s sencilla.<\/p>\n<h2>Dise\u00f1o de una funci\u00f3n para actualizar datos con mutaciones de subdocumentos<\/h2>\n<p>Supongamos ahora que queremos actualizar documentos dentro de la base de datos. En lugar de recuperar documentos, hacer cambios y luego guardar esos cambios, vamos a enviar los cambios directamente a la base de datos y dejar que la base de datos resuelva las cosas.<\/p>\n<p>Navegue hasta la secci\u00f3n\u00a0<strong>actualizaci\u00f3n<\/strong> y ejecute lo siguiente desde la l\u00ednea de comandos:<\/p>\n<pre class=\"lang:default decode:true\">npm install couchbase joi --save<\/pre>\n<p>Como estamos aceptando datos de usuarios, queremos validar esos datos. No estamos creando datos, por lo que no necesitamos generar claves \u00fanicas.<\/p>\n<p>Abra el archivo\u00a0<strong>actualizar\/update.js<\/strong> e incluya lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">const Couchbase = require(\"couchbase\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        id: Joi.string().required(),\r\n        firstname: Joi.string().optional(),\r\n        lastname: Joi.string().optional()\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        var builder = bucket.mutateIn(validation.value.id);\r\n        if(validation.value.firstname) {\r\n            builder.replace(\"firstname\", validation.value.firstname);\r\n        }\r\n        if(validation.value.lastname) {\r\n            builder.replace(\"lastname\", validation.value.lastname);\r\n        }\r\n        builder.execute((error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    statusCode: 500,\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                statusCode: 200,\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>\u00bfLe resulta familiar el c\u00f3digo anterior? Deber\u00eda, porque seguimos la misma estrategia.<\/p>\n<p>Nuestra l\u00f3gica de validaci\u00f3n es ligeramente diferente en este ejemplo:<\/p>\n<pre class=\"lang:default decode:true\">var schema = Joi.object().keys({\r\n    id: Joi.string().required(),\r\n    nombre: Joi.string().optional(),\r\n    apellido: Joi.string().optional()\r\n});<\/pre>\n<p>Queremos editar un documento en particular por lo que se requiere una clave. No sabemos lo que el usuario quiere actualizar as\u00ed que establecemos las propiedades como opcionales.<\/p>\n<p>Para hacer actualizaciones vamos a hacer operaciones de subdocumento en nuestros documentos. Para ello, podemos utilizar un constructor de mutaci\u00f3n.<\/p>\n<pre class=\"lang:default decode:true\">var builder = bucket.mutateIn(validaci\u00f3n.valor.id);\r\nif(validaci\u00f3n.valor.nombre) {\r\n    builder.replace(\"nombre\", validaci\u00f3n.valor.nombre);\r\n}\r\nif(validaci\u00f3n.valor.apellido) {\r\n    builder.replace(\"apellido\", validaci\u00f3n.valor.apellido);\r\n}<\/pre>\n<p>Proporcionamos un documento para alterar y las rutas en las que existen las propiedades. Las rutas pueden ser mucho m\u00e1s complejas que los ejemplos utilizados aqu\u00ed.<\/p>\n<p>Con el conjunto de mutaciones definido, podemos ejecutarlas contra la base de datos.<\/p>\n<pre class=\"lang:default decode:true\">builder.execute((error, result) =&gt; {\r\n    if(error) {\r\n        respuesta = {\r\n            statusCode: 500,\r\n            cuerpo: JSON.stringify({\r\n                c\u00f3digo: error.code\r\n                mensaje: mensaje.error\r\n            })\r\n        };\r\n        reject(respuesta);\r\n    }\r\n    response = {\r\n        statusCode: 200,\r\n        body: JSON.stringify(validaci\u00f3n.valor)\r\n    };\r\n    resolve(response);\r\n});<\/pre>\n<p>Dependiendo del resultado, se devolver\u00e1 una respuesta de la invocaci\u00f3n de la funci\u00f3n.<\/p>\n<h2>Dise\u00f1ar una funci\u00f3n para eliminar datos<\/h2>\n<p>Estamos en la \u00faltima funci\u00f3n de un paquete de operaciones CRUD. Ha llegado el momento de eliminar datos de la base de datos.<\/p>\n<p>Navegue hasta el\u00a0<strong>borrar<\/strong> y ejecute el siguiente comando:<\/p>\n<pre class=\"lang:default decode:true\">npm install couchbase joi --save<\/pre>\n<p>Estaremos aceptando claves de documentos para ser borrados por lo que necesitaremos validar la entrada. Del mismo modo tambi\u00e9n necesitamos el SDK de Couchbase para trabajar con la base de datos.<\/p>\n<p>Abra el archivo\u00a0<strong>delete\/delete.js<\/strong> e incluya el siguiente c\u00f3digo JavaScript:<\/p>\n<pre class=\"lang:default decode:true\">const Couchbase = require(\"couchbase\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        id: Joi.string().required()\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        bucket.remove(validation.value.id, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>Probablemente est\u00e1s viendo el panorama general ahora en lo que respecta a la creaci\u00f3n de funciones con OpenWhisk y Couchbase, por lo que no vamos a caminar a trav\u00e9s de la funci\u00f3n anterior para eliminar documentos.<\/p>\n<h2>Empaquetado y despliegue de las funciones en OpenWhisk con Docker<\/h2>\n<p>Tenemos un conjunto de funciones listas, pero no podemos empaquetarlas y desplegarlas en Bluemix. Si lo hici\u00e9ramos, obtendr\u00edamos un mont\u00f3n de errores. Bluemix utiliza un sabor especial de Linux con una arquitectura determinada. He descargado las dependencias en mi Mac que no es compatible.<\/p>\n<p>\u00bfRecuerdas el art\u00edculo que escrib\u00ed hace un tiempo titulado,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/deploying-native-nodejs-dependencies-aws-lambda\/\" target=\"_blank\" rel=\"noopener\">Implementaci\u00f3n de dependencias de Node.js nativo en AWS Lambda<\/a>? Necesitamos hacer algo similar para OpenWhisk con Docker.<\/p>\n<p>Con Docker instalado y listo para funcionar, ejecute lo siguiente desde la CLI:<\/p>\n<pre class=\"lang:default decode:true\">docker pull openwhisk\/nodejs6action\r\ndocker run -it -v \/Users\/nraboy\/Desktop\/couchbase-openwhisk:\/project openwhisk\/nodejs6action \/bin\/bash<\/pre>\n<p>Los comandos anteriores descargar\u00e1n una imagen Docker OpenWhisk apropiada para Node.js. Luego desplegaremos un contenedor con esa imagen en modo terminal interactivo. Este contenedor tambi\u00e9n tendr\u00e1 un volumen mapeado. Estoy mapeando mi directorio local del proyecto a un directorio dentro del contenedor.<\/p>\n<p>Despu\u00e9s de que el comando se haya ejecutado y el contenedor se haya desplegado, deber\u00edas estar en el shell dentro del contenedor.<\/p>\n<p>Para cada funci\u00f3n, ejecute lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">cd \/proyecto\/crear\r\nnpm instalar<\/pre>\n<p>Recuerda, instalar las dependencias desde nuestra m\u00e1quina anfitriona no es suficiente. Necesitamos compilar las dependencias para Bluemix. Docker compilar\u00e1 estas dependencias y como el directorio est\u00e1 mapeado, podemos utilizarlas desde la m\u00e1quina anfitriona.<\/p>\n<p>Una vez instalados los paquetes de cada funci\u00f3n, podemos empaquetarlos y desplegarlos.<\/p>\n<p>Desde la m\u00e1quina anfitriona, cree un archivo ZIP de cada una de las funciones. El archivo debe contener\u00a0<strong>paquete.json<\/strong> el archivo JavaScript y el archivo\u00a0<strong>node_modules<\/strong> directorio.<\/p>\n<p>Si est\u00e1s en un Mac o en un ordenador con ZIP CLI, ejecuta lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">cd crear\r\nzip -r crear.zip *<\/pre>\n<p>Cuando tengas un ZIP de cada funci\u00f3n, se pueden desplegar ejecutando lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">bx wsk action create couchbase\/delete --kind nodejs:default delete.zip -p host ec2-45-236-32-140.compute-1.amazonaws.com -p username demo -p password bluemix -p bucketName example<\/pre>\n<p>He introducido algunas cosas nuevas en el comando anterior.<\/p>\n<p>En primer lugar, vamos a crear un paquete llamado\u00a0<strong>couchbase<\/strong> y en este paquete tenemos un\u00a0<strong>borrar<\/strong> basada en la funci\u00f3n\u00a0<strong>borrar.zip<\/strong> archivo. Tambi\u00e9n estoy pasando algunos par\u00e1metros por defecto. Estos par\u00e1metros ser\u00e1n nuestra informaci\u00f3n de conexi\u00f3n. Como esta informaci\u00f3n es sensible, no los estamos pasando al invocar la funci\u00f3n, sino al crear la funci\u00f3n.<\/p>\n<p>Ejecute una variaci\u00f3n del comando anterior para cada una de sus funciones.<\/p>\n<p>Para ejecutar su funci\u00f3n, intente ejecutar algo como lo siguiente:<\/p>\n<pre class=\"lang:default decode:true\">bx wsk action invoke couchbase\/create -p firstname Nic -p lastname Raboy --blocking<\/pre>\n<p>El comando anterior debe pasar algunos par\u00e1metros para pasar la validaci\u00f3n. La funci\u00f3n se invoca de forma bloqueante, y si tiene \u00e9xito, nuestros datos se guardar\u00e1n en la base de datos y se devolver\u00e1n en la respuesta.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>Acabas de ver c\u00f3mo crear un paquete de funciones sin servidor para OpenWhisk que se comunican con la base de datos NoSQL, <a href=\"https:\/\/www.couchbase.com\/blog\/es\/\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a>. OpenWhisk puede utilizarse como alternativa a AWS Lambda, pero no son las \u00fanicas opciones disponibles. Independientemente de lo que elijas, las funciones como servicio (FaaS) son soluciones muy escalables para aplicaciones masivas.<\/p>\n<p>\u00bfQuieres ver otro ejemplo de OpenWhisk? Echa un vistazo a un tutorial que escrib\u00ed titulado,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/convert-nodejs-restful-api-serverless-openwhisk\/\">Convierte una API RESTful de Node.js a Serverless con OpenWhisk<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Si has estado al d\u00eda con mi contenido, recordar\u00e1s que hab\u00eda escrito un art\u00edculo titulado, Use AWS Lambda and API Gateway with Node.js and Couchbase NoSQL. En este art\u00edculo hab\u00edamos explorado el uso de los servicios Serverless de Amazon para crear Lambda [...]<\/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":[1814,1816,1822],"tags":[2134,2115,2133,1725,2099],"ppma_author":[9032],"class_list":["post-4542","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-couchbase-server","category-node-js","tag-actions","tag-faas","tag-functions","tag-nosql-database","tag-serverless"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL<\/title>\n<meta name=\"description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\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=\"2018-02-08T15:00:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T01:45:48+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=\"13 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"dateModified\":\"2025-06-14T01:45:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"},\"wordCount\":1857,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"actions\",\"faas\",\"functions\",\"NoSQL Database\",\"serverless\"],\"articleSection\":[\"Application Design\",\"Couchbase Server\",\"Node.js\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\",\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"dateModified\":\"2025-06-14T01:45:48+00:00\",\"description\":\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\"}]},{\"@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":"Utilizar OpenWhisk para FaaS con Node.js y Couchbase NoSQL","description":"Aprenda a crear y desplegar aplicaciones altamente escalables como funciones utilizando OpenWhisk en Bluemix para FaaS y Couchbase para datos NoSQL JSON.","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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_locale":"es_MX","og_type":"article","og_title":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","og_description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2018-02-08T15:00:16+00:00","article_modified_time":"2025-06-14T01:45:48+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":"13 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","datePublished":"2018-02-08T15:00:16+00:00","dateModified":"2025-06-14T01:45:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"wordCount":1857,"commentCount":3,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["actions","faas","functions","NoSQL Database","serverless"],"articleSection":["Application Design","Couchbase Server","Node.js"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","name":"Utilizar OpenWhisk para FaaS con Node.js y Couchbase NoSQL","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-02-08T15:00:16+00:00","dateModified":"2025-06-14T01:45:48+00:00","description":"Aprenda a crear y desplegar aplicaciones altamente escalables como funciones utilizando OpenWhisk en Bluemix para FaaS y Couchbase para datos NoSQL JSON.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#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\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL"}]},{"@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\/4542","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=4542"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/4542\/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=4542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=4542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=4542"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=4542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}