ปัญหาของ promise hell ใน JavaScript
คุณทราบอยู่แล้วว่าพรอมิสถูกสร้างขึ้นเพื่อ แก้ไขปัญหาของ callback hell อย่างไรก็ตาม ภายหลังปรากฏว่าพรอมิส ก็สามารถสร้างโค้ดที่ซับซ้อนได้เช่นกัน ปัญหานี้ ถูกเรียกโดยเปรียบเทียบว่า promise hell
มาดูปัญหานี้จากตัวอย่างโค้ดกัน
สมมติว่าเรามีฟังก์ชัน getSmth
ที่รับพารามิเตอร์และส่งคืนผลลัพธ์
ขึ้นอยู่กับพารามิเตอร์นั้น:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
ในกรณีนี้เรากำลังจำลองการดำเนินการที่มีประโยชน์บางอย่าง (เช่น การรับข้อมูลจากเซิร์ฟเวอร์) สำหรับการจำลอง เราเพียงแค่ส่งผ่านตัวเลขเป็นพารามิเตอร์ และหลังจากผ่านไปหนึ่งวินาทีก็ส่งคืน กำลังสองของตัวเลขนั้น
ทีนี้ลองใช้ฟังก์ชันของเรา
getSmth ภายในฟังก์ชันอื่น:
function func() {
getSmth(2).then(res => {
console.log(res); // จะแสดง 4
});
}
func();
ปัญหาที่หนึ่ง
โครงสร้าง then หลายอันที่ต่อกัน
ทำให้เข้าใจโค้ดได้ยาก:
function func(){
getSmth(2).then(res1 => {
// ทำอะไรบางอย่าง
}).then(res2 => {
// ทำอะไรบางอย่าง
}).then(res3 => {
// ทำอะไรบางอย่าง
}).then(res4 => {
// ทำอะไรบางอย่าง
}).then(res5 => {
// ทำอะไรบางอย่าง
}).then(res6 => {
// ทำอะไรบางอย่าง
});
}
func();
ปัญหาที่สอง
ยังมีปัญหาอีกประเภทหนึ่ง สมมติว่าตอนนี้ เราต้องการใช้ฟังก์ชันของเราสอง ครั้ง จากนั้นหาผลรวมของผลลัพธ์ เป็นผลให้ เราได้โค้ดแบบนี้:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // จะแสดง 13
});
});
}
func();
เริ่มคล้ายกับ callback hell แล้วใช่ไหม? ลองเพิ่มการเรียกใช้ฟังก์ชันอีกหนึ่งครั้ง - โค้ดจะ แย่ลงไปอีก:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
แน่นอนว่า สามารถใช้ Promise.all ได้:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
อย่างไรก็ตาม เราได้สิ่งเดียวกันหรือไม่? ไม่! ในกรณีแรกแต่ละฟังก์ชันใหม่จะรอให้ พรอมิสก่อนหน้าสำเร็จ ในขณะที่ในกรณีที่สอง - พรอมิสทั้งหมดทำงานพร้อมกัน ความแตกต่างนี้จะมีนัยสำคัญในกรณีที่ เราต้องการส่ง การเรียกก่อนหน้าไปยังฟังก์ชันถัดไป:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();