Kesalahan
Mari kita bicara tentang kesalahan.
Ada dua jenis kesalahan:
- kesalahan yang diharapkan
- kesalahan tak terduga
- kesalahan satu per satu
Kesalahan yang Diharapkan
Kesalahan yang diharapkan adalah keadaan di mana hal yang salah terjadi tetapi Anda tahu bahwa itu mungkin terjadi, jadi Anda menanganinya.
Ini adalah hal-hal seperti input pengguna atau permintaan server. Anda tahu pengguna mungkin membuat kesalahan atau bahwa server mungkin turun, jadi Anda menulis beberapa kode pemeriksaan untuk memastikan bahwa program meminta input lagi, atau menampilkan pesan, atau apa pun perilaku lain yang sesuai.
Ini dapat dipulihkan saat ditangani. Jika dibiarkan, mereka menjadi kesalahan yang tidak terduga.
Kesalahan Tidak Terduga
Kesalahan tak terduga (bug) adalah keadaan di mana hal yang salah terjadi karena kode salah. Anda tahu bahwa mereka pada akhirnya akan terjadi, tetapi tidak ada cara untuk mengetahui di mana atau bagaimana menghadapinya karena, menurut definisi, mereka tidak terduga.
Ini adalah hal-hal seperti kesalahan sintaksis dan logika. Anda mungkin memiliki kesalahan ketik dalam kode Anda, Anda mungkin telah memanggil fungsi dengan parameter yang salah. Ini biasanya tidak dapat dipulihkan.
try..catch
Mari kita bicarakan try..catch
.
Dalam JavaScript, throw
tidak umum digunakan. Jika Anda mencari-cari contoh dalam kode mereka akan sedikit dan jauh di antara, dan biasanya terstruktur di sepanjang baris
function example(param) {
if (!Array.isArray(param) {
throw new TypeError('"param" should be an array!');
}
...
}
Karena itu, try..catch
blok tidak terlalu umum untuk aliran kontrol. Biasanya cukup mudah untuk menambahkan beberapa cek sebelum memanggil metode untuk menghindari kesalahan yang diharapkan.
Lingkungan JavaScript juga cukup memaafkan, sehingga kesalahan yang tak terduga seringkali juga diabaikan.
try..catch
tidak harus biasa. Ada beberapa kasus penggunaan yang bagus, yang lebih umum dalam bahasa seperti Java dan C #. Java dan C # memiliki keunggulan mengetikcatch
konstruksi yang , sehingga Anda dapat membedakan antara kesalahan yang diharapkan dan yang tidak terduga:
C # :
try
{
var example = DoSomething();
}
catch (ExpectedException e)
{
DoSomethingElse(e);
}
Contoh ini memungkinkan pengecualian tak terduga lainnya mengalir dan ditangani di tempat lain (seperti dengan cara login dan menutup program).
Dalam JavaScript, konstruk ini dapat direplikasi melalui:
try {
let example = doSomething();
} catch (e) {
if (e instanceOf ExpectedError) {
DoSomethingElse(e);
} else {
throw e;
}
}
Bukan sebagai elegan, yang merupakan bagian dari alasan mengapa itu tidak biasa.
Fungsi
Mari kita bicara tentang fungsi.
Jika Anda menggunakan prinsip tanggung jawab tunggal , setiap kelas dan fungsi harus melayani tujuan tunggal.
Sebagai contoh authenticate()
dapat mengotentikasi pengguna.
Ini dapat ditulis sebagai:
const user = authenticate();
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
Atau dapat juga ditulis sebagai:
try {
const user = authenticate();
// keep doing stuff
} catch (e) {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
}
Keduanya bisa diterima.
Janji
Mari kita bicara tentang janji.
Janji adalah bentuk asinkron dari try..catch
. Memanggil new Promise
atau Promise.resolve
memulai try
kode Anda . Memanggil throw
atau Promise.reject
mengirim Anda ke catch
kode.
Promise.resolve(value) // try
.then(doSomething) // try
.then(doSomethingElse) // try
.catch(handleError) // catch
Jika Anda memiliki fungsi asinkron untuk mengautentikasi pengguna, Anda dapat menuliskannya sebagai:
authenticate()
.then((user) => {
if (user == null) {
// keep doing stuff
} else {
// handle expected error
}
});
Atau dapat juga ditulis sebagai:
authenticate()
.then((user) => {
// keep doing stuff
})
.catch((e) => {
if (e instanceOf AuthenticationError) {
// handle expected error
} else {
throw e;
}
});
Keduanya bisa diterima.
Bersarang
Mari kita bicara tentang bersarang.
try..catch
bisa disarangkan. authenticate()
Metode Anda mungkin secara internal memiliki try..catch
blok seperti:
try {
const credentials = requestCredentialsFromUser();
const user = getUserFromServer(credentials);
} catch (e) {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
}
Demikian juga janji bisa disarangkan. authenticate()
Metode async Anda mungkin menggunakan janji secara internal:
requestCredentialsFromUser()
.then(getUserFromServer)
.catch((e) => {
if (e instanceOf CredentialsError) {
// handle failure to request credentials
} else if (e instanceOf ServerError) {
// handle failure to get data from server
} else {
throw e; // no idea what happened
}
});
Jadi apa jawabannya?
Ok, saya pikir sudah waktunya bagi saya untuk benar-benar menjawab pertanyaan:
Apakah kegagalan dalam otentikasi dianggap sebagai sesuatu yang Anda tolak janji?
Jawaban paling sederhana yang bisa saya berikan adalah bahwa Anda harus menolak janji di mana pun Anda ingin throw
pengecualian jika itu kode sinkron.
Jika aliran kontrol Anda lebih sederhana dengan melakukan beberapa if
pemeriksaan dalam then
laporan Anda , tidak perlu menolak janji.
Jika aliran kontrol Anda lebih sederhana dengan menolak janji dan kemudian memeriksa jenis kesalahan dalam kode penanganan kesalahan Anda, maka lakukan itu.
reject
dan tidak kembali palsu, tetapi jika Anda mengharapkan nilai menjadiBool
, maka Anda berada sukses dan Anda harus menyelesaikan dengan Bool terlepas dari nilai. Janji adalah semacam proxy untuk nilai - mereka menyimpan nilai yang dikembalikan, jadi hanya jika nilainya tidak dapat diperoleh jika Andareject
. Kalau tidak, Anda seharusnyaresolve
.