Devolver llamada al infierno significa que está dentro de una devolución de llamada o dentro de otra devolución de llamada y va a la enésima llamada hasta que no se satisfagan sus necesidades.
Entendamos a través de un ejemplo de llamada falsa ajax usando la API de tiempo de espera establecido, supongamos que tenemos una API de recetas, necesitamos descargar todas las recetas.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
En el ejemplo anterior, después de 1,5 segundos, cuando el temporizador expira, el código de devolución de llamada se ejecutará, en otras palabras, a través de nuestra llamada falsa ajax, todas las recetas se descargarán del servidor. Ahora necesitamos descargar los datos de una receta en particular.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
Para descargar los datos de una receta en particular, escribimos código dentro de nuestra primera devolución de llamada y pasamos el Id de la receta.
Ahora digamos que necesitamos descargar todas las recetas del mismo editor de la receta cuyo id es 7638.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
setTimeout(id=>{
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
console.log(`${id}: ${recipe.title}`);
setTimeout(publisher=>{
const recipe2 = {title:'Fresh Apple Pie', publisher:'Suru'};
console.log(recipe2);
}, 1500, recipe.publisher);
}, 1500, recipeId[2])
}, 1500);
}
getRecipe();
</script>
</body>
Para satisfacer nuestras necesidades, que es descargar todas las recetas del nombre del editor suru, escribimos el código dentro de nuestra segunda devolución de llamada. Está claro que escribimos una cadena de devolución de llamada que se llama infierno de devolución de llamada.
Si desea evitar el infierno de devolución de llamada, puede usar Promise, que es la función js es6, cada promesa recibe una devolución de llamada que se llama cuando una promesa está completa. promesa de devolución de llamada tiene dos opciones: se resuelve o se rechaza. Suponga que su llamada a la API es exitosa, puede llamar a resolver y pasar datos a través de la resolución , puede obtener estos datos usando then () . Pero si su API falló, puede usar el rechazo, use catch para detectar el error. Recuerde que una promesa siempre use entonces para resolver y atrapar para rechazar
Resolvamos el problema del infierno de devolución de llamada anterior usando una promesa.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
getIds.then(IDs=>{
console.log(IDs);
}).catch(error=>{
console.log(error);
});
</script>
</body>
Ahora descargue una receta particular:
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
getIds.then(IDs=>{
console.log(IDs);
return getRecipe(IDs[2]);
}).
then(recipe =>{
console.log(recipe);
})
.catch(error=>{
console.log(error);
});
</script>
</body>
Ahora podemos escribir otro método llamado allRecipeOfAPublisher como getRecipe que también devolverá una promesa, y podemos escribir otro then () para recibir la promesa de resolución para allRecipeOfAPublisher, espero que en este punto puedas hacerlo tú mismo.
Así que aprendimos cómo construir y consumir promesas, ahora hagamos que consumir una promesa sea más fácil usando async / await que se introduce en es8.
<body>
<script>
const getIds = new Promise((resolve, reject)=>{
setTimeout(()=>{
const downloadSuccessfull = true;
const recipeId = [83938, 73838, 7638];
if(downloadSuccessfull){
resolve(recipeId);
}else{
reject('download failed 404');
}
}, 1500);
});
const getRecipe = recID => {
return new Promise((resolve, reject)=>{
setTimeout(id => {
const downloadSuccessfull = true;
if (downloadSuccessfull){
const recipe = {title:'Fresh Apple Juice', publisher:'Suru'};
resolve(`${id}: ${recipe.title}`);
}else{
reject(`${id}: recipe download failed 404`);
}
}, 1500, recID)
})
}
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
getRecipesAw();
</script>
</body>
En el ejemplo anterior, usamos una función asíncrona porque se ejecutará en segundo plano, dentro de la función asíncrona usamos la palabra clave await antes de cada método que devuelve o es una promesa porque esperar en esa posición hasta que se cumpla esa promesa, en otras palabras en el debajo de los códigos hasta que getIds se complete resuelto o el programa de rechazo dejará de ejecutar códigos debajo de esa línea cuando los ID regresen, luego llamamos nuevamente a la función getRecipe () con un id y esperamos usando la palabra clave await hasta que se devuelvan los datos. Así es como finalmente nos recuperamos del infierno de las devoluciones de llamada.
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
Para usar await, necesitaremos una función asíncrona, podemos devolver una promesa, así que use luego para resolver promesa y cath para rechazar promesa
del ejemplo anterior:
async function getRecipesAw(){
const IDs = await getIds;
const recipe = await getRecipe(IDs[2]);
return recipe;
}
getRecipesAw().then(result=>{
console.log(result);
}).catch(error=>{
console.log(error);
});