Diferencia entre revisiones de «JavaScript ES7»

De Wiki Proyectos Beta
Ir a la navegación Ir a la búsqueda
 
(No se muestran 2 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
JavaScript 7, ECMAScript (ES7 o ES2016).
JavaScript 7, ECMAScript (ES7 o ES2016) es el estándar que sigue JavaScript que se lanzó en el 2016.


= Principales novedades de ES7 =
= Principales novedades de ES7 =
Línea 70: Línea 70:


Entonces si la promesa es rechazada, saltará al método catch() y esta vez veremos un mensaje diferente en la consola.
Entonces si la promesa es rechazada, saltará al método catch() y esta vez veremos un mensaje diferente en la consola.
==== Usos prácticos ====
===== Ejemplos =====
====== Ejemplo 1 ======
Recibiendo parámetros.
function randomDelayed(max = 10, expected = 5, delay =  1000) {
return new Promise((resolve, reject) => {
const number = Math.floor(
Math.random() * max)
);
setTimeout(
() => number > expected
? resolve(number)
: reject(new Error('número menor al esperado'));
delay
);
});
}
randomDelayed(100, 75, 2500)
    .then(number => console.log(number))
    .catch(error => console.error(error));
====== Ejemplo 2 ======
Documentación sobre Promise.all: [https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Promise/all ES]
Promesas en paralelo.
Hasta ahora solo vimos como ejecutar una función asíncrona a la vez, sin embargo es muy común que necesitemos realizar múltiples al tiempo, por ejemplo para obtener varios datos de un API. Para eso la clase Promise tiene un método estático llamado '''Promise.all''' el cual recibe un único parámetro, una lista de promesas las cuales se ejecutan simultáneamente, si alguna de estas es rechazadas entonces toda la lista lo es, pero si todas se resuelven entonces podemos obtener una lista de todas las respuestas.
import { resolve } from 'path';
Promise.all([readFile('./archivo1.txt'), readFile('./archivo2.txt')])
.then(data => data.map(resolve))
.then(data => Promise.all(data.map(readFile)))
.then(finalData => console.log(finalData))
.catch(error => console.error(error));
Lo que hacemos en el ejemplo de arriba es leer 2 archivos al tiempo, eso nos devuelve una lista (data) de contenidos, los cuales contienen la ruta para otro archivo, los convertimos entonces a una nueva lista de rutas absolutas (resolve) y usamos esas rutas para crear una nueva lista de promesas a partir de readFile. Si en algún momento ocurrió un error lo mostramos como tal en consola, si todo se resuelve bien entonces escribimos en consola la lista de contenidos de archivos.


== Fetch API ==
== Fetch API ==

Revisión actual - 10:59 29 ago 2022

JavaScript 7, ECMAScript (ES7 o ES2016) es el estándar que sigue JavaScript que se lanzó en el 2016.

Principales novedades de ES7

Spread or Rest Operator (...)

Promesas (Promise)

Una promesa en JavaScript es similar a una promesa en la vida real. Cuando hacemos una promesa en la vida real, es una garantía de que vamos a hacer algo en el futuro. Porque las promesas solo se pueden hacer para el futuro.

Cuando definimos una promesa en JavaScript, se resolverá cuando llegue el momento, o será rechazada.

Una Promesa es un objeto. Hay 3 estados del objeto Promesa:

  • Pendiente: estado inicial, antes de que la promesa tenga éxito o falle.
  • Resuelto: promesa completada.
  • Rechazado: promesa fallida.

Observaciones

  • Cuando solicitamos datos del servidor mediante una Promesa, estará en modo pendiente hasta que recibamos nuestros datos. Si logramos obtener la información del servidor, la Promesa se resolverá con éxito. Pero si no obtenemos la información, entonces la Promesa estará en el estado rechazado.

Recursos

  • MDN Web ES

Creación

Se crea un promesa con dos parámetros, uno para el éxito (resolve) y otro para el error (reject). Finalmente habrá una condición. Si se cumple la condición, la promesa se resolverá, de los contrario será rechazada.

const miPromesa = new Promise((resolve, reject) => {  
   let condition;  
   
   if(condicion) {    
       resolve('La promesa se resuelve con éxito!!!');  
   } else {    
       reject('La promesa es rechazada!!!');  
   }
});

Uso

then

Si la Promesa se resuelve (caso de éxito), algo sucederá después (depende de lo que hagamos con la promesa exitosa).

 miPromesa.then();

Se llama al método then() después de que se resuelva la promesa . Entonces podemos decidir qué hacer con la Promesa resuelta.

Ejemplo

Registremos el mensaje en la consola lo que obtuvimos de la promesa:

miPromesa.then((message) => {  
   console.log(message);
});
catch

Si la Promesa falla, entonces, necesitamos usar el método catch(). Del mismo modo que utilizamos el método then(). También podemos utilizar el método catch() justo después de then().

Ejemplo
miPromesa.then((message) => { 
   console.log(message);
}).catch((message) => { 
   console.log(message);
});

Entonces si la promesa es rechazada, saltará al método catch() y esta vez veremos un mensaje diferente en la consola.

Usos prácticos

Ejemplos
Ejemplo 1

Recibiendo parámetros.

function randomDelayed(max = 10, expected = 5, delay =  1000) {

return new Promise((resolve, reject) => { const number = Math.floor( Math.random() * max) );

setTimeout( () => number > expected ? resolve(number) : reject(new Error('número menor al esperado')); delay ); });

}

randomDelayed(100, 75, 2500)
    .then(number => console.log(number))
    .catch(error => console.error(error));
Ejemplo 2

Documentación sobre Promise.all: ES

Promesas en paralelo.

Hasta ahora solo vimos como ejecutar una función asíncrona a la vez, sin embargo es muy común que necesitemos realizar múltiples al tiempo, por ejemplo para obtener varios datos de un API. Para eso la clase Promise tiene un método estático llamado Promise.all el cual recibe un único parámetro, una lista de promesas las cuales se ejecutan simultáneamente, si alguna de estas es rechazadas entonces toda la lista lo es, pero si todas se resuelven entonces podemos obtener una lista de todas las respuestas.

import { resolve } from 'path';

Promise.all([readFile('./archivo1.txt'), readFile('./archivo2.txt')])

.then(data => data.map(resolve)) .then(data => Promise.all(data.map(readFile))) .then(finalData => console.log(finalData)) .catch(error => console.error(error));

Lo que hacemos en el ejemplo de arriba es leer 2 archivos al tiempo, eso nos devuelve una lista (data) de contenidos, los cuales contienen la ruta para otro archivo, los convertimos entonces a una nueva lista de rutas absolutas (resolve) y usamos esas rutas para crear una nueva lista de promesas a partir de readFile. Si en algún momento ocurrió un error lo mostramos como tal en consola, si todo se resuelve bien entonces escribimos en consola la lista de contenidos de archivos.

Fetch API

El API fetch es un nuevo estándar que viene a dar una alternativa para interactuar por HTTP, con un diseño moderno, basado en promesas, con mayor flexibilidad y capacidad de control a la hora de realizar llamadas al servidor.

El API Fetch está soportado de forma nativa por Edge 14, Firefox 39, Chrome 42 y Opera 29. Para Internet Explorer 10 o Safari 6.1 o superiores o versiones anteriores de Firefox o Chrome, podemos utilizar el polyfill publicado por Github https://github.com/github/fetch.

Recursos

  • MDN Web EN

Partes importantes

Funcionamiento básico

Una de las características más importantes del API fetch es que utiliza promesas, es decir, devuelve un objeto con dos métodos, uno then() y otro catch() a la que pasaremos una función que será invocada cuando se obtenga la respuesta o se produzca un error.

Aquí hay que aclarar un punto con los errores: si se devuelve un código HTTP correspondiente a un error no se ejecutará el catch(), ya que se ha obtenido una respuesta válida, por lo que se ejecutará el then(). Sólo si hay un error de red o de otro tipo se ejecutará el catch().

Otro aspecto importante que hay que comprender es que para obtener el body o cuerpo del mensaje devuelto por el servidor deberemos obtener una segunda promesa por medio de los métodos del objeto Response. Por ello será muy habitual ver dos promesas encadenadas, una para el fetch() y otra con el retorno del método que utilicemos para obtener el body.

Ejemplo API fetch básico

 fetch('https://httpbin.org/ip')
   .then(function(response) {
       return response.text();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Observaciones:

  • Hemos llamado a fetch() con la URL a la que queremos acceder como parámetro.
  • Esta llamada nos devuelve una promesa.
  • El método then() de esa promesa nos entrega un objeto response.
  • Del objeto response llamamos al método text() para obtener el cuerpo retornado en forma de texto.
  • Nos devuelve otra promesa que se resolverá cuando se haya obtenido el contenido.
  • El método then() de esa promesa recibe el cuerpo devuelto por el servidor en formato de texto.
  • Hemos incluido un catch() por si se produce algún error.

Opciones de fetch()

En el ejemplo anterior no hemos indicado que método teníamos que utilizar, simplemente hemos pasado la URL y se considera que queremos utilizar el método GET que es el valor por defecto. La forma de configurar esta llamada es utilizar el segundo parámetro de fetch(), donde pasaremos un objeto con las opciones.

Ejemplo:

 fetch('https://httpbin.org/post', {
       method: 'POST',
       headers: {
           'Content-Type': 'application/x-www-form-urlencoded'
       },
       body: 'a=1&b=2'
   })
   .then(function(response) {
       console.log('response =', response);
       return response.json();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Response

En la función que pasamos a then() vamos a recibir un objeto Response. Este objeto contiene la respuesta que hace el servidor y dispone de una serie de propiedades con los valores de esa respuesta.

Ejemplo response.json()

 fetch('https://httpbin.org/ip')
   .then(function(response) {
       console.log('response.body =', response.body);
       console.log('response.bodyUsed =', response.bodyUsed);
       console.log('response.headers =', response.headers);
       console.log('response.ok =', response.ok);
       console.log('response.status =', response.status);
       console.log('response.statusText =', response.statusText);
       console.log('response.type =', response.type);
       console.log('response.url =', response.url);
       return response.json();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Observaciones: El contenido del body no está disponible directamente en este objeto Response y tenemos que llamar uno de los métodos disponibles para que nos devuelva una promesa donde recibiremos el valor enviado por el servidor. Los métodos disponibles son:

  • response.text() para que nos devuelve el contenido en formato texto.
  • response.json() para que lo devuelva como objeto Javascript.
  • response.arrayBuffer() para obtenerlo como ArrayBuffer.
  • response.blob() como valor que podemos manejar con URL.createObjectURL().
  • response.formData() para obtenerlos como FormData.

Una característica que tenemos que tener en cuenta es que solo podemos hacer una obtención de body, tras la cual ya no podemos volver solicitar otra conversión. Para resolver esta situación el objeto Response tiene el método clone() que nos permite duplicar el objeto y hacer múltiples gestiones de body.

Request

Una forma alternativa de configurar el comportamiento de fetch() es crear un objeto Request y pasar este objeto como parámetro a fetch(). El constructor de Request recibe dos parámetros: la URL y el objeto con las opciones.

Ejemplo objeto Request:

 let request = new Request('https://httpbin.org/get', {
       method: 'GET',
       mode: 'cors',
       credentials: 'omit',
       cache: 'only-if-cached',
       referrerPolicy: 'no-referrer'
   });
 console.log('request =', request);
 fetch(request)
   .then(function(response) {
       console.log('response =', response);
       return response.text();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Observaciones: Este objeto Response puede ser de utilidad si tenemos que hacer varias llamadas con los mismos valores, ya que podemos reutilizarlo tantas veces como nos haga falta. Acepta todas las configuraciones que vimos en fetch().

Headers

Aunque podemos incluir las cabeceras por medio del objeto Request o como parte del objeto que se pasa como segundo parámetro a fetch(), tenemos a nuestra disposición el objeto Headers que nos ayuda a gestionar las cabeceras de una forma más precisa.

Ejemplo Header():

 let headers = new Headers();
 headers.append('a', '1');
 headers.append('b', '2');
 let request = new Request('https://httpbin.org/get', {
       headers: headers
 });
 console.log('request =', request);
 for (var k of request.headers.keys()) {
   console.log('request.headers.get("' + k + '") =', request.headers.get(k));
 }
 fetch(request)
   .then(function(response) {
       console.log('response =', response);
       for (var k of response.headers.keys()) {
           console.log('response.headers.get("' + k + '") =', response.headers.get(k));
       }
       return response.text();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Observaciones: El objeto Headers se puede asignar a Request, pero también está presente en Response con las cabeceras que nos devuelve el servidor. Si queremos consultar las cabeceras devueltas tenemos que utilizar los métodos que ofrece Headers:

  • Headers.append(key, value): añade un valor a una cabecerá ya existe o crea una nueva cabecera si no existe.
  • Headers.delete(key): borra una cabecera.
  • Headers.entries(): retorna un iterador con todas las parejas clave/valor.
  • Headers.get(key): devuelve el primer valor de una cabecera.
  • Headers.getAll(key): devuelve una matriz con todos los valores de una cabecera.
  • Headers.has(key): comprueba si una cabecera existe.
  • Headers.keys(): devuelve un interador con todas las claves.
  • Headers.set(key, value): añade una cabecera nueva.
  • Headers.values(): devuelve un iterador con todos los valores.

FormData

API fetch se apoya en otros API estandarizados como el API FormData, para poder construir de una forma más completa el body con el contenido de un formulario.

Este API se puede utilizar de dos formas, una es pasando un objeto form del DOM al constructor de FormData, por ejemplo: new FormData(document.getElementById('myForm'), la otra creando un objeto con new FormData() e ir incluyendo los valores uno a uno por medio de los métodos append() o set().

Ejemplo FormData():

 let dataSend = new FormData();
 dataSend.append('a', '1');
 dataSend.append('b', '2');
 let request = new Request('https://httpbin.org/put', {
   method: 'PUT',
   body:      dataSend
 });
 console.log('request =', request);
 for (var k of dataSend.keys()) {
   console.log('dataSend.get("' + k + '") =', dataSend.get(k));
 }
 fetch(request)
   .then(function(response) {
       console.log('response =', response);
       return response.text();
   })
   .then(function(data) {
       console.log('data = ', data);
   })
   .catch(function(err) {
       console.error(err);
   });

Observaciones:

  • No ha sido necesario incluir una cabecera Content-Type, ya que se añade directamente al asociar body a un objeto FormData.

Async and Await

Closure

Nuevo método para arrays - includes

Nueva sintaxis para Potenciación de números