en pocas palabras.
Las promesas permiten envolver peticiones asíncronas y encadenarlas para evitar el conocido callback hell
, por lo que el código es mas fácil de entender y mantener.
Peticiones sin Promesas
En la antigüedad cuando se requería realizar una solicitud asíncrona a un servidor se tenía que utilizar el objeto XMLHttpRequest
, en el cual se tenía que indicar un callback para manejar el resultado.
const req = new XMLHttpRequest();
req.addEventListener("load", function () {
console.log(this.responseText);
});
req.open("GET", "http://somedomain/service1");
req.send();
Esto no tenía ninguna complicación siempre y cuando solo necesitaramos una sola petición, pero la realidad nunca es tan simple, en algunos casos requeriamos realizar una segunda petición justo cuando la primera terminara correctamente, y luego de esa segunda, tal vez otra y asi sucesivamente.
Para lograr esto tras cada petición se tenía que realizar una solicitud en el callback exitoso con la nueva petición y esto generaba un callback, dentro de otro callback y asi sucesivamente por lo que se caería en lo que se conoce como callback hell
.
const req1 = new XMLHttpRequest();
req1.addEventListener("load", function () {
if (this.status == 200) {
const req2 = new XMLHttpRequest();
req2.open("GET", "http://somedomain/service2");
req2.addEventListener("load", function () {
// aqui otra petición y asi sucesivamente
});
req2.send();
}
});
req1.open("GET", "http://somedomain/service1");
req1.send();
por suerte para nosotros llegaron las promesas y en vez de tener un callback dentro de otro callback, ahora podemos encadenar promesas con .then()
continua leyendo para entender como vamos a hacerlo.
Envolviendo Peticiones
Si queremos resolver el problema de callback hell
con nuestro famoso XMLHttpRequest
vamos a necesitar convertirlo en promesa para luego poder encadenar cada petición y hacer nuestro código mas limpio y mantenible gracias a las promesas.
function makeRequest(){
return new Promise(function(resolve,reject){
const req = new XMLHttpRequest();
req.addEventListener("load", function () {
if (req.status == 200) {
resolve(req.response);
}else{
reject('error');
}
});
req.open("GET", "http://somedomain/service1");
req.send();
});
}
makeRequest().then(
function(result){
//en caso de que todo este bien
},
function(result){
//en caso de error
}
);
Envolver requiere algo de esfuerzo, pero la buena noticia es que actualmente contamos con fetch, el cual automaticamente devuelve una promesa y no tenemos que realizar este trabajo de envolver cada petición. A continuación el mismo ejemplo pero usando fetch.
function makeRequest(){
return fetch("http://somedomain/service1");
}
makeRequest().then(
function(result){
//en caso de que todo este bien
},
function(result){
//en caso de error
}
);
Encadenando Promesas
Encadenar promesas es la gracia de las promesas, de esta manera evitamos el conocido callback hell
y nuestro código crece de forma mas ordenada. Resulta que tras la ejecución de una promesa podemos acceder al resultando con el metodo .then()
, el cual lo podemos utilizar para devolver una promesa y con ello el código crece de forma lineal y no en forma de un callback dentro de un callback, asi evitando el callback hell
.
function req1(){
return fetch("http://somedomain/service1");
}
function req2(){
return fetch("http://somedomain/service2");
}
req1()
.then(function(response){
//resultado de la primera solicitud.
return req2();
})
.then(function(response){
//resultado de la segunda solicitud.
}); //podriamos seguir encadenando mas peticiones.
Otros Detalles
Algunos detalles importantes de las promesas fueron excluidos debido a que podrian generar confusión, sin embargo son importantes estudiarlos y entenderlos en detalle.
- Las promesas tienen gestion de errores y estan se controlan con el metodo
.catch()
- El método
.then()
tiene sobrecarga de su método tanto en sus parámetros como en el valor retornado. Esto podría confundir, asi que leer atentamente este método. - muchos desarrolladores no suelen utilizar una función para la creación de la promesa, en vez de ello utilizan la promesa directamente ejemplo:
fetch("http://somedomain/service1").then(...)
al igualmente para los valores retornados, ejemplo: returnfetch("http://somedomain/service2");
- Debido a que puede ser complejo aprender y utilizar correctamente las promesas en la forma clasica (como se presenta en este árticulo) se creo async/await, esta utilizan las promesas, y permite que el código sea mas fácil de entender, aprender y mantener.
Conclusiones
- Las promesas nacen de la necesidad para que el código sea mas ordenado y fácil de mantener evitando el callback hell.
- Las promesas pueden ser difíciles de entender por lo que lo que aprenderlas y utilizarlas correctamente puede tomar algo de tiempo.
Gracias por leer.
Leave a Reply