L'enfer de rappel signifie que vous êtes à l'intérieur d'un rappel d'un autre rappel et qu'il passe au nième appel jusqu'à ce que vos besoins ne soient pas satisfaits.
Comprenons à travers un exemple de faux appel ajax en utilisant l'API set timeout, supposons que nous ayons une API de recette, nous devons télécharger toutes les recettes.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
Dans l'exemple ci-dessus, après 1,5 seconde, lorsque la minuterie expire, le code de rappel sera exécuté, en d'autres termes, grâce à notre faux appel ajax, toutes les recettes seront téléchargées depuis le serveur. Nous devons maintenant télécharger les données d'une recette particulière.
<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>
Pour télécharger une donnée de recette particulière, nous avons écrit du code à l'intérieur de notre premier rappel et passé l'ID de recette.
Disons maintenant que nous devons télécharger toutes les recettes du même éditeur de la recette dont l'ID est 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>
Pour répondre à tous nos besoins, c'est-à-dire télécharger toutes les recettes du nom d'éditeur suru, nous avons écrit du code à l'intérieur de notre deuxième rappel. Il est clair que nous avons écrit une chaîne de callback qui s'appelle Callback Hell.
Si vous voulez éviter l'enfer des rappels, vous pouvez utiliser Promise, qui est la fonctionnalité js es6, chaque promesse prend un rappel qui est appelé lorsqu'une promesse est remplie. Le rappel de promesse a deux options: il est résolu ou rejeté. Supposons que votre appel API aboutisse, vous pouvez appeler la résolution et transmettre les données via la résolution , vous pouvez obtenir ces données en utilisant then () . Mais si votre API échoue, vous pouvez utiliser le rejet, utiliser catch pour attraper l'erreur. Rappelez - vous une promesse de toujours utiliser alors pour résoudre et prises pour rejeter
Résolvons le problème précédent de l'enfer des rappels en utilisant une promesse.
<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>
Maintenant, téléchargez une recette particulière:
<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>
Maintenant, nous pouvons écrire une autre méthode appelée allRecipeOfAPublisher comme getRecipe qui renverra également une promesse, et nous pouvons en écrire une autre then () pour recevoir la promesse de résolution pour allRecipeOfAPublisher, j'espère qu'à ce stade, vous pourrez le faire vous-même.
Nous avons donc appris à construire et à consommer des promesses, facilitons maintenant la consommation d'une promesse en utilisant async / await qui est introduit dans 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>
Dans l'exemple ci-dessus, nous avons utilisé une fonction async car elle s'exécutera en arrière-plan, à l'intérieur de la fonction async nous avons utilisé le mot-clé await avant chaque méthode qui retourne ou est une promesse car attendre sur cette position jusqu'à ce que cette promesse se réalise, en d'autres termes dans le les codes ci-dessous jusqu'à ce que getIds soit résolu ou le programme de rejet cessera d'exécuter les codes sous cette ligne lorsque les ID sont retournés, puis nous avons à nouveau appelé la fonction getRecipe () avec un identifiant et avons attendu en utilisant le mot-clé await jusqu'à ce que les données soient renvoyées. C'est ainsi que nous avons finalement récupéré de l'enfer du rappel.
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
Pour utiliser await, nous aurons besoin d'une fonction asynchrone, nous pouvons renvoyer une promesse, alors utilisez-la pour résoudre la promesse et cath pour rejeter la promesse
à partir de l'exemple ci-dessus:
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);
});