Ahora que sabes lo básico, hagamos algo más complejo.
Vamos a asumir que los mensajes contienen una URL válida, como esta:
123{"url": "https://google.com"}
json
Usando el QR Code API, vamos a crear una imagen QR a partir de una URL y luego convertir el QR para añadir al mensaje su representación base64. Por último, guardaremos esta representación en la tienda de valores clave. De esta forma, la próxima vez que el mensaje contenga la misma URL, podremos obtenerla desde allí en lugar de llamar a la API.
Puedes encontrar el código final de este manejador de eventos en esta lista en caso de que lo necesites.
Muy bien, crea otro Antes de Publicar o Disparar EH (no es necesario usar el proceso guiado):
Ahora modifiquemos el código para registrar la solicitud, llamemos a la API con algunos datos de muestra y registremos su respuesta para ver cómo se ve:
123456789101112131415161718exportdefaultrequest=={const pubnub =require("pubnub");const kvstore =require("kvstore");const xhr =require("xhr");console. log(request);// Registrar el sobre de la solicitud passreturn xhr .fetch(`https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=Ejemplo`,{}).then(response= >{console.log(response);return request.ok();});};
javascript
Publica un mensaje. Deberías recibir algo como lo siguiente:
12345612:06:34 js: {"verbo": "publicar", "pubis": "pub-c-2e6a21d7-9099-4cc1-b77c-b7116015a4e9", "subclave": "sub-c-9fa184ba-13dd-11e7-9093-0619f8945a4f", "timetoken": nulo, "timetoken_v1": nulo, "timetoken_v2": nulo, "versión": "v1", "meta": { "clientip": "189.196.255.59", "origen": "ps8.pubnub.com", "useragent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, como Gecko) Chrome/56.0.2924.87 Safari/537.36" }, "params": { "uuid": "4aca78b8-312d-475b-9142-d935cc6b6906", "pnsdk": "PubNub-JS-Web/3.16.3", "timestamp": "1490724394", "firma": "j8XyUFtpb7jILr_TnWB6Y_b84Rr3ryzNko5jY6JPBo4=" }, "uri": "/publish/pub-c-2e6a21d7-9099-4cc1-b77c-b7116015a4e9/sub-c-9fa184ba-13dd-11e7-9093-0619f8945a4f/0/qr/0/%7B%22foo%22%3A%22bar%22%2C%22id%22%3A42%2C%22text%22%3A%22BLOCKS%22%7D", "channels": [ "qr" ], "callback": "0", "mensaje": { "foo": "bar", "id": 42, "texto": "BLOQUES" } }12:06:35 js: { "cuerpo": "�PNGr001au001au0000u0000u0000u0000u0000u0000�u0000u0000Nu0000�u0001u0003u0000Nu0006���u0000u0000u0000Nu0006PLTE���u0000u0000\Nu0000U��~u0000u0000\Nu0000�IDATH�͖�Nr�0fDNu001d�H�NNb��ђ�Nu0018�u0011()P��Nu0004��E��E�E�u001eu0014$0027�l#�u0012ENu0011�Nu0004�m���cu00104/E��͋�Nu0013����_�Yi���N�M�. ��u001c�.?�u0000\Nu000f�z|8�����hu0006}5��N�����Ɛ�j����Z���3Gk�\Nu00174f��f��b2A�P7�s2Y��$00272Y�������u0010u001e��u0010f�ٕ? u0016�:�(b�U\Nu001f�{<�Nu0017�[�G2�y���Nu0018d��O�Nu0007�]u��*�u?c_�cW|�� �Nu0011�\Nu0000�Nu000f�@u0000u0000Nu0000IEND�B`�", "$buffer": {i1}"tipo".{i} "Buffer", "datos": [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 150, 0, 0, 0, 150, 1, 3, 0, 0, 0, 6, 207, 227, 161, 0, 0, 0, 6, 80, 76, 84, 69, 255, 255, 255, 0, 0, 0, 85, 194, 211, 126, 0, 0, 0, 221, 73, 68, 65, 84, 72, 137, 205, 150, 177, 13, 133, 48, 12, 68, 29, 165, 72, 201, 8, 140, 146, 209, 146, 209, 24, 133, 17, 40, 41, 80, 140, 207, 4, 137, 255, 69, 157, 195, 69, 136, 30, 20, 39, 251, 108, 35, 242, 18, 69, 17, 139, 4, 213, 109, 246, 251, 206, 99, 16, 52, 47, 69, 143, 180, 205, 139, 221, 19, 145, 185, 176, 174, 207, 95, 209, 89, 105, 146, 190, 194, 228, 19, 172, 215, 77, 226, 46, 255, 181, 28, 206, 46, 63, 151, 0, 15, 253, 122, 124, 56, 187, 163, 189, 244, 251, 104, 6, 125, 16, 102, 185, 154, 214, 92, 155, 165, 140, 201, 236, 204, 198, 144, 167, 106, 143, 157, 199, 90, 244, 249, 231, 51, 71, 107, 192, 23, 52, 102, 231, 180, 10, 102, 142, 191, 98, 50, 65, 165, 80, 55, 235, 115, 248, 39, 50, 89, 183, 176, 179, 172, 225, 16, 30, 187, 251, 188, 69, 79, 217, 149, 63, 22, 131, 58, 236, 40, 8, 203, 85, 31, 187, 123, 60, 187, 23, 165, 91, 201, 71, 50, 157, 121, 139, 169, 250, 24, 100, 179, 254, 79, 163, 7, 147, 93, 117, 235, 250, 42, 151, 117, 63, 99, 95, 202, 99, 87, 124, 133, 189, 196, 9, 128, 17, 156, 0, 247, 15, 137, 64, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] }, "cabeceras": { "fecha": "Mar, 28 Mar 2017 18:06:38 GMT", "servidor": "Apache/2", "variar": "Aceptar-codificación, agente de usuario", "longitud del contenido": "296", "conexión": "cerrar", "tipo de contenido": "image/png" }, "url": "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=Example", "status": 200, "statusText": "OK", "ok": true, "bodyUsed": false }12:06:35 (Publicar): { "foo": "bar", "id": 42, "texto": "BLOQUES" }
Se puede ver que el objeto de la solicitud no sólo contiene el mensaje, sino que la parte interesante es la respuesta de la API.
Puedes conocer más opciones para crear un código QR aquí. Sin embargo, por defecto, la API devolverá una imagen PNG en el cuerpo de la respuesta.
Para obtener la representación de la imagen en base64, podríamos usar el Codec/base64:
12const base64Codec =require("codec/base64");console.log(base64Codec.btoa("hola"));// aGVsbG8=
javascript
Sin embargo, esta función btoa está diseñada para datos de cadena más que para datos binarios. Por suerte, la respuesta contiene un búfer , una matriz de bytes que representa la imagen. Podemos usar ese búfer para implementar una función para convertirla en una cadena base64.
Vamos a usar la implementación de Jon Leighton (no hay necesidad de incluirla dentro de la función de exportación):
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556// https://gist.github. com/jonleighton/958841constbase64ArrayBuffer=function(arrayBuffer){var base64 =$0027$0027;var encodificaciones =$0027ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/$0027;var bytes =newUint8Array(arrayBuffer);var byteLength = bytes. byteLength;var byteRemainder = byteLength %3;var mainLength = byteLength - byteRemainder;var a, b, c, d;var chunk;// El bucle principal se ocupa de los bytes en trozos de 3for(var i =0; i < mainLength; i = i +3){// Combina los tres bytes en un solo trozo entero =(bytes[i]<<16)|(bytes[i +1]<<8)| bytes[i +2];// Utiliza máscaras de bits para extraer segmentos de 6 bits del triplete a =(trozo & 16515072)// 16515072 = (2^6 - 1) << 18 b =(chunk &258048)// 258048 = (2^6 - 1) << 12 c =(chunk &4032)// 4032 = (2^6 - 1) < < 6 d = chunk &63;// 63 = 2^6 - 1// Convierte los segmentos binarios en bruto a la base de codificación ASCII apropiada64 += codificaciones[a]+ codificaciones[b]+ codificaciones[c]+ codificaciones[d]; }// Trata los bytes restantes y rellenaif(byteRemainder ==1){ chunk = bytes[mainLength]; a =(chunk &252)>2;// 252 = (2^6 - 1) << 2// Poner a cero los 4 bits menos significativos b =(chunk &3)<<4;// 3 = 2^2 - 1 base64 += codificaciones[a]+ codificaciones[b]+$0027==$0027;}elseif(byteRemainder ==2){ chunk =(bytes[mainLength]<< 8)| bytes[mainLength +1]; a =(chunk &64512)>10;// 64512 = (2^6 - 1) << 10 b =(chunk &1008)>4;// 1008 = (2^6 - 1) << 4// Poner a cero los 2 bits menos significativos c =(chunk &15)<<2;// 15 = 2^4 - 1 base64 += codificaciones[a]+ codificaciones[b]+ codificaciones[c]+$0027=$0027;}retorno base64;};exportdefault(request)={{{i}. ..};
javascript
Entonces, importemos los módulos que vamos a usar:
1234567891011const base64ArrayBuffer =...exportdefault(request)=;{const xhr =require("xhr");const console =require($0027console$0027);const db =require($0027kvstore$0027);const queryStringCodec =require($0027codec/query_string$0027);...};
javascript
Ahora extraigamos la URL del mensaje y codifiquémosla con la ayuda del Codec/query_string junto con un parámetro de tamaño de valor 150×150. La imagen no debe ser grande ya que todo el proceso se hará en memoria. Esta es una forma de codificarlo:
12345678910111213141516171819const base64ArrayBuffer =...exportdefault(request)={...try{const url = request.message. url;const apiParams = queryStringCodec.stringify({ datos: url, tamaño:$0027150x150$0027,});...}catch(e){console.error($0027Excepción no capturada:$0027, e);}};
javascript
A continuación, veamos si la base de datos contiene la URL de una ejecución anterior:
12345678910111213141516171819202122232425const base64ArrayBuffer =...exportdefault(request)={...try{...return db. get(url).then((obj)=...});}catch(e){console.error($0027Uncaught exception:$0027, e);}}};
javascript
Dentro de la promesa de db.get, vamos a devolver otra promesa que resolverá el resultado de la función. Para ello, tenemos que manejar los casos en que el objeto para la URL no existe todavía y cuando ya existe, y ya que estamos tratando con código asíncrono, ambos casos tienen que funcionar con promesas.
Si el objeto para la URL no existe, crearemos una promesa para llamar a la API y guardar el objeto en la base de datos:
123456789101112131415161718192021222324252627282930313233343536373839const base64ArrayBuffer =...exportdefault(request)={...try{...return db.get(url).then((obj)=...{let promise;if(! obj){console.log(`El código QR para ${url} no existe. Creándolo...`); promise =newPromise((resolve)=> xhr.fetch(`https://api.qrserver.com/v1/create-qr-code/?${apiParams}`,{}). then((response)= >//console.log(response);const base64 =base64ArrayBuffer(response["$buffer"].data);const newObj ={ imgBase64: base64, contentType: response.headers["content-type"],}; db. set(url, newObj).catch((err)= >{console.log("Ocurrió un error al salvar el objeto.", err);});resolve(newObj);});}...});}catch(e){console.error($0027Excepción no capturada:$0027, e);}};
javascript
En el código anterior, generamos la cadena de base 64 utilizando los datos del búfer de la respuesta para poder crear un objeto con esta cadena y el tipo de contenido. Luego, guardamos este objeto en la base de datos y lo usamos para resolver la promesa.
Si hay un objeto para el URL ya en la base de datos, sólo creamos una promesa resolviendo a ese objeto.
123456789101112131415161718192021222324const base64ArrayBuffer =...exportdefault(request)={...try{...return db.get(url).then((obj)={{{{{ {dejemos que se prometa;if(! obj){...}else{console.log(`El código QR de ${url} ya existe...`); promise =Promise.resolve(obj);}});}catch(e){console.error($0027Uncaught exception:$0027, e);}};
javascript
De esta manera, en cualquier caso, devolvemos una promesa para que podamos añadir el objeto al mensaje asincrónicamente y terminar la función:
1234567891011121314151617181920212223242526272829const base64ArrayBuffer =...exportdefault(request)={...try{...return db.get(url).then((obj)=...let promise;if(! obj){...}else{...} devolver promesa.then((qrObj)=.request.message.qrCode= qrObj;return request.ok();});});}catch(e){console.error($0027Uncaught exception:$0027, e);}};
javascript
Y hemos terminado. Guarda los cambios, reinicia el bloque, introduce una carga válida y pruébala:
La salida de la consola debería ser algo así:
12312:10:28 js: "data=https%3A%2F%2Fgoogle.com&amp;size=150x150"12:10:30 js: "El código QR para https://google.com no existe. Creándolo... "12:10:31 (Publicar): { "url": "https://google.com", "qrCode": { "imgBase64": "contentType": "image/png" } }
Si se repite la prueba con la misma carga útil, el objeto debe ser retirado de la base de datos:
12312:10:41 (Publicar): { "url": "https://google.com", "qrCode": { "imgBase64": "contentType": "image/png" } }12:10:41 js: "data=https%3A%2F%2Fgoogle.com&amp;size=150x150"12:10:41 js: "El código QR para https://google.com ya existe..."
Si quieres probarlo con un archivo HTML, usa el siguiente código (reemplazando la información de tu PubNub):
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657<! DOCTYPE html;<html;head;<metacharset=utf-8/;w;w;title;PubNub</title;w;/head;w;body;w;inputtype="text"/;w;button;Publish</button;w;br/;br/;br/;w;img/;w;! -- Incluir la biblioteca PubNub --><scriptsrc="https://cdn.pubnub.com/sdk/javascript/pubnub.4 .5.0.js"-->;;/script -->;;scripttype="text/javascript"-->/ Usando la Expresión de Función Invocada Inmediatamente (IIFE) para limitar la variable scope(function(){varCHANNEL=$0027qr$0027;var txtUrl =documento.getElementById($0027txtUrl$0027);var btnPublicar =documento. getElementById($0027btnPublish$0027);var img =documento.getElementById($0027img$0027);<!--InstantiatePubNub--;var pubnub =newPubNub({ publishKey:$0027YOUR_PUBLISH_KEY$0027, subscribeKey:$0027YOUR_SUBSCRIBE_KEY$0027});// Suscríbete al canal pubnub demo_tutorial. addListener({message:function(messageObj){var msg = messageObj.message;console.log(msg) img.setAttribute($0027src$0027,$0027data:$0027+ msg.qrCode.contentType+$0027;base64,$0027+ msg.qrCode.imgBase64);}}); pubnub. subscribe({ channels:[CHANNEL]});// Publicar un simple mensaje en el canal demo_tutorial btnPublish.addEventListener($0027click$0027,function(event){ pubnub.publish({ message:{"url": txtUrl.value}, channel:CHANNEL});});})();</script></body>
html
Esto usará la cadena base64 como la fuente de un elemento img con el formato:
1data:image/png;base64,[BASE64_STRING]
Ábralo en un navegador y vea el resultado: