Masalah Promise Hell dalam JavaScript
Anda telah pun tahu bahawa janji (promise) dicipta untuk menyelesaikan masalah callback hell. Walau bagaimanapun, lama-kelamaan ternyata bahawa janji juga mampu menghasilkan kod yang rumit. Masalah ini dengan analogi dipanggil promise hell.
Mari kita lihat masalah ini dengan contoh
kod. Katakan kita mempunyai fungsi getSmth,
yang menerima parameter dan mengembalikan hasil
bergantung pada parameter tersebut:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
Dalam kes ini, kita mengimitasi beberapa operasi berguna (misalnya, mendapatkan data dari pelayan). Sebagai imitasi, kita hanya menghantar nombor sebagai parameter dan selepas satu saat mengembalikan kuasa dua nombor tersebut.
Sekarang mari kita gunakan fungsi kita
getSmth di dalam fungsi lain:
function func() {
getSmth(2).then(res => {
console.log(res); // akan memaparkan 4
});
}
func();
Masalah Pertama
Banyak konstruksi then yang mengikut satu sama lain
menyukarkan pemahaman kod:
function func(){
getSmth(2).then(res1 => {
// lakukan sesuatu
}).then(res2 => {
// lakukan sesuatu
}).then(res3 => {
// lakukan sesuatu
}).then(res4 => {
// lakukan sesuatu
}).then(res5 => {
// lakukan sesuatu
}).then(res6 => {
// lakukan sesuatu
});
}
func();
Masalah Kedua
Terdapat juga masalah jenis lain. Katakan sekarang kita mahu menggunakan fungsi kita dua kali, kemudian jumlahkan hasilnya. Hasilnya kita akan mendapat kod seperti ini:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // akan memaparkan 13
});
});
}
func();
Sudah menyerupai callback hell, bukan? Mari tambah satu lagi panggilan fungsi - kod akan menjadi lebih teruk:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Sudah tentu, kita boleh menggunakan Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Walau bagaimanapun, adakah kita mendapat perkara yang sama? Tidak! Dalam kes pertama, setiap fungsi baru menunggu janji (promise) sebelumnya selesai, manakala dalam kes kedua - semua janji dilaksanakan serentak. Perbezaan ini akan ketara dalam kes apabila kita mahu menghantar panggilan sebelumnya ke fungsi seterusnya:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();