Pengecualian dalam Rantaian Janji dalam JavaScript
Katakan atas sebab-sebab tertentu janji (promise) kita diselesaikan dengan ralat:
let promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('error');
}, 3000);
});
Dalam kes ini, pelaksanaan kod akan serta-merta beralih
kepada then yang mempunyai fungsi pengendali
ralat, atau kepada catch pertama, bergantung
kepada yang mana ditemui terlebih dahulu.
Berikut adalah contoh situasi pertama:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
},
function(error) {
// pelaksanaan akan serta-merta beralih ke sini
}
).then(
function(result) {
console.log(result);
}
);
Berikut adalah contoh situasi kedua:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// pelaksanaan akan serta-merta beralih ke sini
}
).then(
function(result) {
console.log(result);
}
);
Fungsi pengendali mempunyai dua pilihan tindakan:
jika ia berjaya mengatasi situasi pengecualian,
ia boleh mengembalikan hasil melalui return
dan pelaksanaan akan diteruskan dalam rantai.
Jika ia tidak berjaya mengatasi ralat, ia boleh
sama ada tidak mengembalikan apa-apa, atau melempar pengecualian
melalui throw. Dalam kes ini, pelaksanaan
akan beralih kepada pengendali ralat seterusnya
(dalam then atau catch - yang mana ditemui
terlebih dahulu).
Biasanya, semua ralat dalam rantai ditangkap
di satu tempat: catch diletakkan di hujung
rantai:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
// kita akan sampai ke sini sekiranya berlaku ralat
}
);
Pengecualian boleh berlaku dalam janji (promise) itu sendiri,
atau dilempar melalui throw
dalam mana-mana pautan rantai:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
if (semuanyaBaik) {
return result + '2';
} else {
throw new Error('ralat'); // beralih kepada pengendali terdekat
}
}
)
.then(
function(result) {
return result + '3';
}
).catch(
function(error) {
// pengendali terdekat
}
);
Perhatikan bahawa catch diperlukan khusus untuk
mendiagnosis ralat: sama ada ia boleh diselesaikan atau tidak.
Jika ralat boleh diselesaikan, maka catch hendaklah
menghantar penyelesaiannya kepada then yang berikutnya.
Jika tidak boleh diselesaikan (atau catch ini
secara ringkasnya tidak tahu bagaimana menyelesaikannya), maka kita hendaklah
sama ada tidak mengembalikan apa-apa atau melempar pengecualian:
promise.then(
function(result) {
return result + '1';
}
).then(
function(result) {
return result + '2';
}
).catch(
function(error) {
if (ralatBolehDiselesaikan) {
return 'data'; // hantar ke then berikutnya
} else {
// tidak mengembalikan apa-apa atau lempar pengecualian
}
}
).then(
function(result) {
// selesaikan ralat di sini
}
);