    # Máster en Programación FullStack con JavaScript y Node.js ### JS, Node.js, Frontend, Backend, Firebase, Express, Patrones, HTML5_APIs, Asincronía, Websockets, Testing ## Clase 41 ### Blob  **Soporte** - [Blob constructing](https://caniuse.com/#feat=blobbuilder) - [Blob URLs](https://caniuse.com/#feat=bloburls) **Importante** - Podemos lidiar con `file interface` (input file) - Podemos generar ficheros al vuelo - Podemos convertir el contenido d eun blob en una URL para usarla con etiquetas normales **Recursos** - [Blob en MDN](https://developer.mozilla.org/es/docs/Web/API/Blob) - [Soporte blob urls](http://caniuse.com/#feat=bloburls) - [Soporte blob constructing](http://caniuse.com/#feat=blobbuilder) **Ejemplo básico** ```javascript const blob = new Blob(['body { color: red; }'], {type: 'text/css'}); const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = window.URL.createObjectURL(blob); document.body.appendChild(link); ``` ### Blob: Propiedades **[Blob.type](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type)** ```javascript // <input type="file" multiple id="ficheros"> // Permitimos solo *.png, *.jpeg and *.gif images const allowedFileTypes = ["image/png", "image/jpeg", "image/gif"]; const fileInput = document.getElementById("ficheros"); const files = fileInput.files; for (let i = 0; i < files.length; i++) { const validFile = allowedFileTypes.indexOf(files[i].type) > -1 console.log(`${files[i]} ${validFile ? "es válido" : "NO es válido"}`) }); ``` **[blob.size](https://developer.mozilla.org/es/docs/Web/API/Blob/size)** ```javascript // <input type="file" multiple id="ficheros"> const fileInput = document.getElementById("ficheros"); const files = fileInput.files; for (let i = 0; i < files.length; i++) { console.log(`${files[i].name} tiene ${files[i].size} Bytes`); } ``` ### Blob: Métodos **[Blob.slice()]()** ```javascript const contenido = ['<a id="a"><b id="b">hey!</b></a>']; const miFichero = new Blob(contenido, {type : 'text/html'}); const blobParcial = miFichero.slice(1,10, "text/plain"); ``` ### FileSystem  **Importante** - [NO ESTA SOPORTADO AÚN AL 100%](https://developer.mozilla.org/es/docs/Web/API/FileSystem#Browser_compatibility) - Permite el almacenamiento de ficheros de forma temporal o persistente - Es necesario pedir permisos - Estan en su propio sandbox - [Introduction to the File and Directory Entries API](https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Introduction#Restrictions) **Funcionalidades** - Lectura y manipulación de archivos ([File/Blob](https://developer.mozilla.org/es/docs/Web/API/Blob), [FileList](https://developer.mozilla.org/es/docs/Web/API/FileList), [FileReader](https://developer.mozilla.org/es/docs/Web/API/FileReader), - Creación y escritura ([BlobBuilder](https://developer.mozilla.org/es/docs/Web/API/BlobBuilder), FileWriter), - Acceso a sistemas de archivos y directorios ([DirectoryReader](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryReader), [DirectoryEntry](https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryEntry), [LocalFileSystem](https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem)). **Recuros** - [HTML5 Rocks! | Cómo explorar las API de sistemas de archivos (FileSystem APIs)](https://www.html5rocks.com/es/tutorials/file/filesystem/) - [MDN | FileSystem](https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Introduction) ### Web Workers: Intro  - Los Web Workers se ejecutan en un subproceso aislado. - Funcionan aunque la pagina se haya cerrado - Siguen funcionando aunque el navegadro se cierre. - [Especificación](http://www.whatwg.org/specs/web-workers/current-work/) - [Soporte](http://caniuse.com/#feat=webworkers) **Arquitectura**  **Alcance** - En el contexto de un Worker, tanto self como this hacen referencia al alcance global del Worker - Puede acceder a: - Objeto navigator - Objeto location (de solo lectura) - XMLHttpRequest - setTimeout(), setInterval(), etc... - [Caché de la aplicación](https://developer.mozilla.org/es/docs/Web/API/Window/applicationCache) - Importación de secuencias de comandos externas, [importScripts()](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts) - Generación de otros Web Workers **Limitaciones** - No se ejecutarán de forma local - DOM - Objeto window - Objeto document - Objeto parent **Recomendaciones** - Obtención previa y/o almacenamiento en caché de datos para un uso futuro - Métodos para destacar la sintaxis de código u otros formatos de texto en tiempo real - Corrector ortográfico - Análisis de datos de vídeo o audio - Entrada y salida en segundo plano o solicitud de servicios web - Procesamiento de conjuntos o respuestas JSON de gran tamaño - Filtrado de imágenes en <canvas> - Actualización de varias filas de una base de datos web local **Ejemplos** - [Web Workers and Service Workers](http://codepen.io/ruzz311/pen/NNroab) - [WEB Worker sample](http://codepen.io/nacholozano/pen/dpqvYk) **Recursos** - [Introducción a los Web Workers en html5rocks](https://www.html5rocks.com/es/tutorials/workers/basics/) - [Web workers without a separate Javascript file?](http://stackoverflow.com/questions/5408406/web-workers-without-a-separate-javascript-file) - [Offline Recipes for Service Workers by DWB](https://davidwalsh.name/offline-recipes-service-workers) - [Using Web Workers to Speed-Up Your JavaScript Applications by treehouse](http://blog.teamtreehouse.com/using-web-workers-to-speed-up-your-javascript-applications) - [Debugging Web Workers with Chrome Developer Tools](https://blog.chromium.org/2012/04/debugging-web-workers-with-chrome.html) - [Using Web Workers en MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) - [Concurrency in JavaScript](http://typedarray.org/concurrency-in-javascript/) **Librerías** - [parallel.js](https://github.com/parallel-js/parallel.js) - [promise-worker](https://github.com/nolanlawson/promise-worker) - [Catiline.js](http://catilinejs.com/) ### Web Workers: Básico  **Definición y puesta en marcha** - Instanciando el Web Worker ```javascript const worker = new Worker('fichero.js'); ``` - Arrancando el Web Worker ```javascript const worker = new Worker('fichero.js'); worker.postMessage(); ``` **Comunicación** - Desde el archivo principal ```javascript const worker = new Worker('fichero.js'); worker.addEventListener('message', evento => { console.log('El worker dice: ', evento.data); }, false); worker.postMessage('Hola Mundo!'); ``` - Desde el Web Worker ```javascript self.addEventListener('message', evento => { self.postMessage(evento.data); }, false); ``` **Parar un Web Worker** - Desde el archivo principal ```javascript worker.terminate() ``` - Desde el Web Worker ```javascript self.close() ``` #### Web Workers: Avanzado **Subworkers** - La resolución de las URI de los Subworkers está relacionada con la ubicación de su Worker principal (en oposición a la página principal) - Los Workers tienen la capacidad de generar Workers secundarios. - Los Subworkers deben estar alojados en el mismo origen que la página principal. **Blob** En el HTML: ```html <!-- inline worker --> <script id="worker" type="javascript/worker"> ((s => { const increment = 1; let count = 0; const loop = 999999999; s.onmessage = e => { console.log(e.data); let test = 0; for( let i = 0 ; i < loop ;i++ ){ test = i; const int = Math.trunc( i*100/loop ); if( int === count ){ s.postMessage( int ); count += increment; } } s.postMessage( {finish:'loop finished'} ); }; }))(self); </script> ``` En JS: ```javascript const blob = new Blob([document.querySelector('#worker').textContent], { type: "text/javascript" }); const worker = new Worker(window.URL.createObjectURL(blob)); ``` **Shared Web Workers** - [Epecificación](https://html.spec.whatwg.org/multipage/workers.html#sharedworker) - [Soporte Shared Web Workers](http://caniuse.com/#feat=sharedworkers) **Definición y puesta en marcha** - Instanciando el Web Worker ```javascript const worker = new SharedWorker("fichero.js"); ``` - Arrancando el Web Worker utiliznado port ```javascript const worker = new SharedWorker("/html5/web-worker-shared.jsp"); worker.port.addEventListener("message", event => { console.log("datos del ShraedWorker", event.data); }, false); worker.port.start(); ``` **Comunicación** - Desde el archivo principal ```javascript const worker = new SharedWorker("/html5/web-worker-shared.jsp"); worker.port.addEventListener("message", event => { console.log("datos del ShraedWorker", event.data); }, false); worker.port.postMessage("First Message"); ``` - Desde el Web Worker ```javascript const ports = []; onconnect = event => { const port = event.ports[0]; ports.push(port); port.start(); port.addEventListener("message", event => { listenForMessage(event, port); } ); } listenForMessage = (event, port) => { port.postMessage(`Reply from SharedWorker to: ${event.data}`); } //Implementation of shared worker thread code setInterval(() => { runEveryXSeconds() }, 5000); function runEveryXSeconds() { for(i = 0; i < ports.length; i++) { ports[i].postMessage(`Calling back at : ${new Date().getTime()}`); } } ```