Misalkan saya memiliki kode berikut.
function divide(numerator, denominator) {
return new Promise((resolve, reject) => {
if(denominator === 0){
reject("Cannot divide by 0");
return; //superfluous?
}
resolve(numerator / denominator);
});
}
Jika tujuan saya adalah menggunakan reject
untuk keluar lebih awal, haruskah saya membiasakan return
diri juga setelahnya?
Jawaban:
The
return
tujuannya adalah untuk mengakhiri pelaksanaan fungsi setelah penolakan, dan mencegah eksekusi kode setelah.Dalam hal ini mencegah
resolve(numerator / denominator);
dari mengeksekusi, yang tidak sepenuhnya diperlukan. Namun, masih lebih baik untuk menghentikan eksekusi untuk mencegah kemungkinan jebakan di masa depan. Selain itu, ini adalah praktik yang baik untuk mencegah menjalankan kode yang tidak perlu.Latar Belakang
Sebuah janji bisa ada di salah satu dari 3 negara:
Ketika sebuah janji dipenuhi atau ditolak, itu akan tetap di negara ini tanpa batas waktu (diselesaikan). Jadi, menolak janji yang dipenuhi atau memenuhi janji yang ditolak, tidak akan berpengaruh.
Cuplikan contoh ini menunjukkan bahwa meskipun janji itu dipenuhi setelah ditolak, tetap saja ditolak.
Jadi mengapa kita harus kembali?
Meskipun kami tidak dapat mengubah status janji yang telah ditentukan, menolak atau menyelesaikan tidak akan menghentikan eksekusi seluruh fungsi. Fungsi ini mungkin berisi kode yang akan membuat hasil membingungkan. Sebagai contoh:
Bahkan jika fungsi tidak mengandung kode seperti itu sekarang, ini menciptakan kemungkinan jebakan di masa depan. Refactor di masa depan mungkin mengabaikan fakta bahwa kode tersebut masih dieksekusi setelah janji ditolak, dan akan sulit untuk di-debug.
Menghentikan eksekusi setelah menyelesaikan / menolak:
Ini adalah hal-hal aliran kontrol JS standar.
resolve
/reject
:Tampilkan cuplikan kode
resolve
/reject
- karena nilai balik dari callback diabaikan, kita dapat menyimpan garis dengan mengembalikan pernyataan tolak / tekad:Tampilkan cuplikan kode
Tampilkan cuplikan kode
Saya lebih suka menggunakan salah satu
return
opsi karena kodenya lebih rata.sumber
return
ada atau tidak karena setelah negara janji telah ditetapkan, itu tidak dapat diubah sehingga panggilanresolve()
setelah panggilanreject()
tidak akan melakukan apa pun kecuali menggunakan beberapa siklus CPU tambahan. Saya sendiri akan menggunakanreturn
keadilan dari sudut pandang kode dan efisiensi, tetapi tidak diperlukan dalam contoh khusus ini.Promise.try(() => { })
bukan Janji baru dan hindari menggunakan tekad / tolak panggilan. Alih-alih, Anda bisa menulis yangreturn denominator === 0 ? throw 'Cannot divide by zero' : numerator / denominator;
saya gunakanPromise.try
sebagai sarana untuk memulai suatu Janji serta menghilangkan janji-janji yang dibungkus dengan blok try / catch yang bermasalah.reject
itu melakukan sesuatu yang mahal, seperti terhubung ke database atau titik akhir API? Semua itu tidak perlu dan memerlukan biaya dan sumber daya, terutama misalnya jika Anda terhubung ke sesuatu seperti database AWS atau titik akhir API Gateway. Dalam hal ini Anda pasti akan menggunakan pengembalian untuk menghindari kode yang tidak perlu dieksekusi.return
.Sebuah idiom umum, yang mungkin atau mungkin bukan cangkir teh Anda, adalah untuk menggabungkan
return
denganreject
, untuk secara bersamaan menolak janji dan keluar dari fungsi, sehingga sisa fungsi termasuk yangresolve
tidak dijalankan. Jika Anda menyukai gaya ini, itu bisa membuat kode Anda sedikit lebih kompak.Ini berfungsi dengan baik karena konstruktor Janji tidak melakukan apa pun dengan nilai pengembalian, dan dalam hal apa pun
resolve
sertareject
tidak mengembalikan apa pun.Idiom yang sama dapat digunakan dengan gaya panggilan balik yang ditunjukkan dalam jawaban lain:
Sekali lagi, ini berfungsi dengan baik karena orang yang menelepon
divide
tidak mengharapkannya mengembalikan apa pun dan tidak melakukan apa pun dengan nilai pengembalian.sumber
reject
statusSecara teknis tidak diperlukan di sini 1 - karena Janji dapat diselesaikan atau ditolak, secara eksklusif dan hanya sekali. Hasil Janji pertama menang dan setiap hasil selanjutnya diabaikan. Ini berbeda dari panggilan balik gaya Node.
Yang sedang dikatakan itu adalah praktik bersih yang baik untuk memastikan bahwa tepat seseorang dipanggil, ketika praktis, dan memang dalam kasus ini karena tidak ada proses async / ditangguhkan lebih lanjut. Keputusan untuk "kembali lebih awal" tidak berbeda dengan mengakhiri fungsi apa pun ketika pekerjaannya selesai - vs. melanjutkan pemrosesan yang tidak terkait atau tidak perlu.
Kembali pada waktu yang tepat (atau menggunakan kondisional untuk menghindari mengeksekusi kasus "lain") mengurangi kemungkinan kode berjalan secara tidak sengaja dalam keadaan tidak valid atau melakukan efek samping yang tidak diinginkan; dan karena itu membuat kode kurang rentan terhadap 'melanggar tak terduga'.
1 Jawaban teknis ini juga bergantung pada kenyataan bahwa dalam hal ini kode setelah "kembali", jika dihilangkan, tidak akan menghasilkan efek samping. JavaScript akan dengan senang hati membagi dengan nol dan mengembalikan + Infinity / -Infinity atau NaN.
sumber
Jika Anda tidak "kembali" setelah menyelesaikan / menolak, hal-hal buruk (seperti pengalihan halaman) dapat terjadi setelah Anda bermaksud menghentikannya. Sumber: Saya mengalami ini.
sumber
Jawaban oleh Ori sudah menjelaskan bahwa itu tidak perlu
return
tetapi merupakan praktik yang baik. Perhatikan bahwa konstruktor janji aman, sehingga akan mengabaikan pengecualian yang dilemparkan yang dilewati kemudian, pada dasarnya Anda memiliki efek samping yang tidak dapat Anda amati dengan mudah.Perhatikan bahwa
return
ing awal juga sangat umum dalam panggilan balik:Jadi, sementara itu praktik yang baik dalam janji-janji itu diperlukan dengan panggilan balik. Beberapa catatan tentang kode Anda:
sumber
Dalam banyak kasus dimungkinkan untuk memvalidasi parameter secara terpisah dan segera mengembalikan janji yang ditolak dengan Promise.reject (alasan) .
sumber