Promesas en JavaScript - Coding N Concepts

Las promesas se introducen de forma nativa en ES6. Son muy similares a nuestras promesas. A medida que cumplimos o incumplimos nuestras promesas, las promesas de JavaScript también se resuelven o incumplen. En este artículo, explicaremos por qué debemos usar promesas, sintaxis de promesa, estados de promesa y su uso práctico con ejemplos que usan la API fetch.

Índice
  1. ¿Por qué promesas?
  2. Sintaxis de promesa
  3. estados de promesa
  4. Utilizar
  5. promesas encadenadas
  6. Promesa.todo()
  7. Promise.allSettled()
  8. Promesa.carrera()
  9. Resumen

¿Por qué promesas?

En el pasado, habrías usado recordatorios para manejar operaciones asíncronas. Sin embargo, las devoluciones de llamada tienen una funcionalidad limitada y, a menudo, conducen a un código inmanejable si está manejando varias llamadas asincrónicas, lo que lleva a un código de devolución de llamada muy anidado, también llamado recordatorio infierno.

Se introdujeron promesas para mejorar la legibilidad del código y un mejor manejo de llamadas asincrónicas y errores.

Sintaxis de promesa

Veamos la sintaxis del objeto de promesa simple.

let promise = new Promise(function (resolve, reject) {
  // asynchronous call
});

Promise toma una función de devolución de llamada como argumento y esta función de devolución de llamada toma dos argumentos: el primero es un resolver función, y la segunda es una rechazar Una función. Una promesa puede ser terminado con un valor o rechazado con una razón (error).

estados de promesa

Un objeto de promesa tiene uno de tres estados:

  • esperando: es el estado inicial.
  • lleno: es el estado de éxito. Se llama al método resolve().
  • rechazado: es un estado fallido, se llama al rechazo ().

Utilizar

Por lo general, usamos llamadas asincrónicas con la API Fetch para obtener datos del HTTP puntos finales Veamos el ejemplo, cómo se pueden usar las promesas en tal caso.

//create a promise object
let getUsers = new Promise(function (resolve, reject ){
    fetch('https://jsonplaceholder.typicode.com/users')
    .then(response => {
        return response.json();
    })
    .then(data => {
        resolve(data);
    })
    .catch(error => {
        reject(error);
    });
});

//call promise object
getUsers
.then((data) => {
  console.log(data);
})
.catch(error => {
  console.log(error);
});

promesas encadenadas

El encadenamiento de promesas entra en juego cuando necesita usar la salida de una llamada asíncrona como entrada para otra llamada asíncrona. Puedes encadenar varias promesas en este caso.

Veamos el siguiente ejemplo donde primero buscamos la lista de usuarios que usan getUser llamada asíncrona y luego encadenarla con getPosts pasando el ID de usuario.

//create a common getData function
let getData = (url) => new Promise(function (resolve, reject ){
  fetch(url)
    .then(response => {
        return response.json();
    })
    .then(data => {
        resolve(data);
    })
    .catch(error => {
        reject(error);
    });
});

let getUsers = getData('https://jsonplaceholder.typicode.com/users');
let getPosts = (userId) => getData(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`);

//chained promises to fetch all posts by first user (userId = 1)
getUsers.then((data) => {
  const user = data[0];
  return getPosts(user.id);
})
.then((data) => {
  console.log(data);
})
.catch(error => {
  console.log(error);
});

Output

▼ (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] ➤ 0: {userId: 1, id: 1, title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body: "quia et suscipit↵suscipit recusandae consequuntur …strum rerum est autem sunt rem eveniet architecto"} ➤ 1: {userId: 1, id: 2, title: "qui est esse", body: "est rerum tempore vitae↵sequi sint nihil reprehend…aperiam non debitis possimus qui neque nisi nulla"} ➤ 2: {userId: 1, id: 3, title: "ea molestias quasi exercitationem repellat qui ipsa sit aut", body: "et iusto sed quo iure↵voluptatem occaecati omnis e…↵molestiae porro eius odio et labore et velit aut"} ➤ 3: {userId: 1, id: 4, title: "eum et est occaecati", body: "ullam et saepe reiciendis voluptatem adipisci↵sit … ipsam iure↵quis sunt voluptatem rerum illo velit"} ➤ 4: {userId: 1, id: 5, title: "nesciunt quas odio", body: "repudiandae veniam quaerat sunt sed↵alias aut fugi…sse voluptatibus quis↵est aut tenetur dolor neque"} ➤ 5: {userId: 1, id: 6, title: "dolorem eum magni eos aperiam quia", body: "ut aspernatur corporis harum nihil quis provident …s↵voluptate dolores velit et doloremque molestiae"} ➤ 6: {userId: 1, id: 7, title: "magnam facilis autem", body: "dolore placeat quibusdam ea quo vitae↵magni quis e…t excepturi ut quia↵sunt ut sequi eos ea sed quas"} ➤ 7: {userId: 1, id: 8, title: "dolorem dolore est ipsam", body: "dignissimos aperiam dolorem qui eum↵facilis quibus…↵ipsam ut commodi dolor voluptatum modi aut vitae"} ➤ 8: {userId: 1, id: 9, title: "nesciunt iure omnis dolorem tempora et accusantium", body: "consectetur animi nesciunt iure dolore↵enim quia a…st aut quod aut provident voluptas autem voluptas"} ➤ 9: {userId: 1, id: 10, title: "optio molestias id quia eum", body: "quo et expedita modi cum officia vel magni↵dolorib…it↵quos veniam quod sed accusamus veritatis error"} length: 10 ➤ __proto__: Array(0)

Promesa.todo()

Promise.all() es útil cuando desea ejecutar varias llamadas asincrónicas y esperar a que se completen y obtengan una salida colectiva.

Promise.all() toma una serie de promesas y devuelve una serie de resultados en la misma secuencia de promesas. Lanza una excepción si alguna de las llamadas asincrónicas falla.

Veamos el ejemplo a continuación, donde obtenemos el resultado de tres llamadas asíncronas getUsers, getPosts y getComments todos juntos.

//create a common getData function
let getData = (url) => new Promise(function (resolve, reject ){
  fetch(url)
    .then(response => {
        return response.json();
    })
    .then(data => {
        resolve(data);
    })
    .catch(error => {
        reject(error);
    });
});

//create multiple promises from common getData function
let getUsers = getData('https://jsonplaceholder.typicode.com/users');
let getPosts = getData('https://jsonplaceholder.typicode.com/posts');
let getComments = getData('https://jsonplaceholder.typicode.com/comments');

//fetch data to get users, posts and comments collectively
Promise.all([getUsers, getPosts, getComments]).then(result => {
  console.log(result);
});

Output

▼ (3) [Array(10), Array(100), Array(500)] ➤ 0: (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] ➤ 1: (100) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] ➤ 2: (500) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, …] length: 3 ➤ __proto__: Array(0)

Promise.allSettled()

Promise.allSettled() es similar a Promise.all() para realizar varias llamadas asincrónicas. La única diferencia entre estos dos,

  • Promise.all() se resuelve por completo o se rechaza por completo, lo que significa que si falla una llamada asíncrona, arroja un error.
  • Promise.allSettled() está completamente resuelto, lo que significa que no devuelve un error si falla una llamada asincrónica. Da la salida colectiva de todas las llamadas asincrónicas exitosas y fallidas.

Veamos el siguiente ejemplo, donde getPostsFails La llamada aync devuelve un error 404 porque el punto final de URL no existe, pero aún puede recuperar datos para getUsers y getComments llamadas asíncronas.

//create a common getData function
let getData = (url) => new Promise(function (resolve, reject ){
  fetch(url)
    .then(response => {
        if(response.ok){
          return response.json();
        }else{
          throw `Error ${response.status}`;
        }     
    })
    .then(data => {
        resolve(data);
    })
    .catch(error => {
        reject(error);
    });
});

//create multiple promises from common getData function
let getUsers = getData('https://jsonplaceholder.typicode.com/users');
let getPostsFails = getData('https://jsonplaceholder.typicode.com/postsfailes');
let getComments = getData('https://jsonplaceholder.typicode.com/comments');

//fetch data to get users, posts and comments collectively regardless of any error
Promise.allSettled([getUsers, getPostsFails, getComments]).then(result => {
  console.log(result);
});

Output

▼ (3) [{…}, {…}, {…}] ➤ 0: {status: "fulfilled", value: Array(10)} ➤ 1: {status: "rejected", reason: "Error 404"} ➤ 2: {status: "fulfilled", value: Array(500)} length: 3 ➤ __proto__: Array(0)

Promesa.carrera()

Promise.race() es útil cuando desea recuperar datos de una de varias llamadas asincrónicas, según la primera resolución.

Mire el ejemplo a continuación donde estamos interesados ​​​​en todos los datos sobre getTodos, getUsers y getComments, lo que se resuelva primero. En nuestro caso getUsers resolvió primero y devolvió la lista de usuarios.

Tenga en cuenta que si ejecuta el mismo fragmento de código una y otra vez, el resultado puede diferir según la conectividad de la red y lo que se resuelva primero.

//create a common getData function
let getData = (url) => new Promise(function (resolve, reject ){
  fetch(url)
    .then(response => {
        return response.json();
    })
    .then(data => {
        resolve(data);
    })
    .catch(error => {
        reject(error);
    });
});

//create multiple promises from common getData function
let getTodos = getData('https://jsonplaceholder.typicode.com/todos');
let getUsers = getData('https://jsonplaceholder.typicode.com/users');
let getComments = getData('https://jsonplaceholder.typicode.com/comments');


//fetch either todos or users or comments whichever resolves first
Promise.race([getTodos, getUsers, getComments]).then(result => {
  console.log(result);
});

Output

▼ (10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] ➤ 0: {id: 1, name: "Leanne Graham", username: "Bret", email: "Sincere@april.biz", address: {…}, …} ➤ 1: {id: 2, name: "Ervin Howell", username: "Antonette", email: "Shanna@melissa.tv", address: {…}, …} ➤ 2: {id: 3, name: "Clementine Bauch", username: "Samantha", email: "Nathan@yesenia.net", address: {…}, …} ➤ 3: {id: 4, name: "Patricia Lebsack", username: "Karianne", email: "Julianne.OConner@kory.org", address: {…}, …} ➤ 4: {id: 5, name: "Chelsey Dietrich", username: "Kamren", email: "Lucio_Hettinger@annie.ca", address: {…}, …} ➤ 5: {id: 6, name: "Mrs. Dennis Schulist", username: "Leopoldo_Corkery", email: "Karley_Dach@jasper.info", address: {…}, …} ➤ 6: {id: 7, name: "Kurtis Weissnat", username: "Elwyn.Skiles", email: "Telly.Hoeger@billy.biz", address: {…}, …} ➤ 7: {id: 8, name: "Nicholas Runolfsdottir V", username: "Maxime_Nienow", email: "Sherwood@rosamond.me", address: {…}, …} ➤ 8: {id: 9, name: "Glenna Reichert", username: "Delphine", email: "Chaim_McDermott@dana.io", address: {…}, …} ➤ 9: {id: 10, name: "Clementina DuBuque", username: "Moriah.Stanton", email: "Rey.Padberg@karina.biz", address: {…}, …} length: 10 ➤ __proto__: Array(0)

Resumen

Siempre es mejor usar Promises en lugar de funciones de devolución de llamada, porque Promises tiene mucho que ofrecer en términos de,

  • Solucionar problemas de respuesta de llamada anyc exitosa usando Promise.resolve(response)
  • Rechazar la respuesta de llamada asíncrona según el estado o los datos mediante Promise.reject(response)
  • Mejor manejo de errores usando Promise.catch(onRejection)
  • Encadenamiento de múltiples llamadas asincrónicas usando Promise.then(onFulfillment, onRejection)
  • Obtenga el resultado colectivo de varias llamadas asincrónicas usando Promise.all([promise1, promise2, ...])
  • Obtenga el resultado colectivo de múltiples llamadas asincrónicas independientemente de cualquier error usando Promise.allSettled([promise1, promise2, ...])
  • Obtenga cualquier resultado según cuál se resuelva primero entre muchas llamadas asincrónicas usando Promise.race([promise1, promise2, ...])

Si quieres conocer otros artículos parecidos a Promesas en JavaScript - Coding N Concepts puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas