การเรียกกลับนรกหมายความว่าคุณอยู่ในการโทรกลับภายในการโทรกลับอื่นและจะไปที่การโทรที่ n จนกว่าความต้องการของคุณจะไม่สมบูรณ์
มาทำความเข้าใจกับตัวอย่างการโทร ajax ปลอมโดยใช้ set timeout API สมมติว่าเรามีสูตร API เราต้องดาวน์โหลดสูตรอาหารทั้งหมด
<body>
<script>
function getRecipe(){
setTimeout(()=>{
const recipeId = [83938, 73838, 7638];
console.log(recipeId);
}, 1500);
}
getRecipe();
</script>
</body>
ในตัวอย่างข้างต้นหลังจาก 1.5 วินาทีเมื่อตัวจับเวลาหมดอายุภายในรหัสการโทรกลับจะดำเนินการกล่าวอีกนัยหนึ่งผ่านการโทร ajax ปลอมของเราสูตรทั้งหมดจะดาวน์โหลดจากเซิร์ฟเวอร์ ตอนนี้เราต้องดาวน์โหลดข้อมูลสูตรเฉพาะ
<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>
ในการดาวน์โหลดข้อมูลสูตรเฉพาะเราได้เขียนโค้ดไว้ในการโทรกลับครั้งแรกและส่งรหัสสูตร
สมมติว่าเราต้องดาวน์โหลดสูตรอาหารทั้งหมดของผู้เผยแพร่สูตรเดียวกันซึ่ง id คือ 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>
เพื่อเติมเต็มความต้องการของเราซึ่งก็คือการดาวน์โหลดสูตรอาหารทั้งหมดของชื่อผู้จัดพิมพ์ suru เราได้เขียนโค้ดไว้ในการโทรกลับครั้งที่สองของเรา เห็นได้ชัดว่าเราเขียนห่วงโซ่การเรียกกลับซึ่งเรียกว่านรกเรียกกลับ
หากคุณต้องการหลีกเลี่ยงการโทรกลับคุณสามารถใช้ Promise ซึ่งเป็นคุณสมบัติ js es6 โดยแต่ละคำสัญญาจะเรียกกลับซึ่งเรียกเมื่อคำสัญญาเต็มไปหมด สัญญาว่าจะโทรกลับมีสองตัวเลือกไม่ว่าจะได้รับการแก้ไขหรือปฏิเสธ สมมติเรียก API ของคุณจะประสบความสำเร็จคุณสามารถเรียกแก้ไขและส่งผ่านข้อมูลผ่านการแก้ปัญหาคุณจะได้รับข้อมูลนี้โดยใช้แล้ว () แต่ถ้า API ของคุณล้มเหลวคุณสามารถใช้ปฏิเสธได้ให้ใช้catchเพื่อตรวจจับข้อผิดพลาด อย่าลืมสัญญามักจะใช้แล้วสำหรับการแก้ปัญหาและจับสำหรับการปฏิเสธ
มาแก้ปัญหาการโทรกลับก่อนหน้านี้โดยใช้คำสัญญา
<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>
ดาวน์โหลดสูตรเฉพาะ:
<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>
ตอนนี้เราสามารถเขียนอีกวิธีหนึ่งที่เรียกว่าallRecipeOfAPublisherเช่น getRecipe ซึ่งจะคืนสัญญาและเราสามารถเขียนอีกครั้งแล้ว () เพื่อรับคำสัญญาแก้ไขสำหรับ allRecipeOfAPublisher ฉันหวังว่า ณ จุดนี้คุณสามารถทำได้ด้วยตัวเอง
ดังนั้นเราจึงได้เรียนรู้วิธีสร้างและใช้คำสัญญาตอนนี้มาทำให้การบริโภคสัญญาง่ายขึ้นโดยใช้ async / await ซึ่งเปิดตัวใน 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>
ในตัวอย่างข้างต้นเราใช้ฟังก์ชัน async เพราะมันจะทำงานในพื้นหลังภายในฟังก์ชัน async เราใช้คำหลักรอก่อนที่แต่ละวิธีจะส่งคืนหรือเป็นคำสัญญาเพราะต้องรอตำแหน่งนั้นจนกว่าสัญญานั้นจะสำเร็จกล่าวอีกนัยหนึ่งใน รหัสร้องจนกว่า getIds จะแก้ไขหรือปฏิเสธโปรแกรมจะหยุดการเรียกใช้รหัสดังต่อไปนี้เมื่อ ID ส่งคืนจากนั้นเราเรียกอีกครั้งว่า getRecipe () ฟังก์ชั่นด้วย id และรอโดยใช้คำสำคัญรอจนกว่าข้อมูลจะถูกส่งคืน นี่คือวิธีที่เราฟื้นจากนรกเรียกกลับได้ในที่สุด
async function getRecipesAw(){
const IDs = await getIds;
console.log(IDs);
const recipe = await getRecipe(IDs[2]);
console.log(recipe);
}
ในการใช้ await เราจะต้องมีฟังก์ชัน async เราสามารถคืนสัญญาได้ดังนั้นใช้เพื่อแก้ไขสัญญาและ cath สำหรับการปฏิเสธสัญญา
จากตัวอย่างด้านบน:
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);
});