Oddzwanianie do piekła oznacza, że znajdujesz się w środku oddzwaniania lub w innym wywołaniu zwrotnym i przechodzi do n-tego połączenia, dopóki twoje potrzeby nie zostaną spełnione.
Przyjrzyjmy się przykładowi fałszywego wywołania ajax przy użyciu API set timeout, załóżmy, że mamy API receptury, musimy pobrać całą recepturę.
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
W powyższym przykładzie po upływie 1,5 sekundy, gdy licznik czasu wygaśnie, zostanie wykonany kod wywołania zwrotnego, innymi słowy, za pośrednictwem naszego fałszywego wywołania Ajax cała receptura zostanie pobrana z serwera. Teraz musimy pobrać dane konkretnego przepisu.
<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>
Aby pobrać dane konkretnego przepisu, napisaliśmy kod w naszym pierwszym wywołaniu zwrotnym i przekazaliśmy identyfikator przepisu.
Powiedzmy, że musimy pobrać wszystkie przepisy tego samego wydawcy przepisu o identyfikatorze 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>
Aby w pełni zaspokoić nasze potrzeby, czyli pobrać wszystkie przepisy wydawcy suru, napisaliśmy kod w naszym drugim oddzwonieniu. Jasne jest, że napisaliśmy łańcuch wywołań zwrotnych, który nazywa się piekło zwrotnych.
Jeśli chcesz uniknąć piekła oddzwaniania, możesz użyć Promise, która jest funkcją js es6, każda obietnica przyjmuje wywołanie zwrotne, które jest wywoływane, gdy obietnica jest pełna. obietnica callback ma dwie opcje: zostanie rozwiązana lub odrzucona. Załóżmy, że wywołanie interfejsu API zakończyło się pomyślnie, możesz wywołać metodę rozwiązywania i przekazywać dane przez rozwiązanie , możesz uzyskać te dane za pomocą metody then () . Ale jeśli twój interfejs API zawiódł, możesz użyć odrzucenia, użyj catch, aby złapać błąd. Pamiętaj obietnicę zawsze używać wtedy dla determinacji i połowu do odrzucenia
Rozwiążmy poprzedni problem z piekłem oddzwonienia, używając obietnicy.
<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>
Teraz pobierz konkretny przepis:
<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>
Teraz możemy napisać inną metodę call allRecipeOfAPublisher, taką jak getRecipe, która również zwróci obietnicę, i możemy napisać inną metodę then (), aby otrzymać obietnicę rozwiązania dla allRecipeOfAPublisher, mam nadzieję, że w tym momencie możesz to zrobić samodzielnie.
Więc nauczyliśmy się, jak konstruować i konsumować obietnice, teraz ułatwmy korzystanie z obietnic, używając async / await, które zostało wprowadzone w 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>
W powyższym przykładzie użyliśmy funkcji async, ponieważ będzie działać w tle, wewnątrz funkcji async użyliśmy słowa kluczowego await przed każdą metodą, która zwraca lub jest obietnicą, ponieważ czekamy na tę pozycję, aż obietnica zostanie spełniona, innymi słowy w poniżej kody, dopóki getIds nie zostaną rozwiązane lub odrzucone, program przestanie wykonywać kody poniżej tej linii, gdy zwrócone zostaną identyfikatory, a następnie ponownie wywołaliśmy funkcję getRecipe () z identyfikatorem i czekaliśmy za pomocą słowa kluczowego await, aż zwrócone zostaną dane. Więc tak w końcu doszliśmy do siebie z piekła oddzwaniania.
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
Aby użyć await, będziemy potrzebować funkcji asynchronicznej, możemy zwrócić obietnicę, więc użyj jej do rozwiązania obietnicy i odpowiedzi na obietnicę odrzucenia
z powyższego przykładu:
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);
});