Saya sedang menulis kode yang melakukan sesuatu yang terlihat seperti:
function getStuffDone(param) { | function getStuffDone(param) {
var d = Q.defer(); /* or $q.defer */ | return new Promise(function(resolve, reject) {
// or = new $.Deferred() etc. | // using a promise constructor
myPromiseFn(param+1) | myPromiseFn(param+1)
.then(function(val) { /* or .done */ | .then(function(val) {
d.resolve(val); | resolve(val);
}).catch(function(err) { /* .fail */ | }).catch(function(err) {
d.reject(err); | reject(err);
}); | });
return d.promise; /* or promise() */ | });
} | }
Seseorang mengatakan kepada saya bahwa ini disebut " antipattern ditangguhkan " atau " Promise
antipattern konstruktor " masing-masing, apa yang buruk tentang kode ini dan mengapa ini disebut antipattern ?
javascript
promise
q
bluebird
es6-promise
Benjamin Gruenbaum
sumber
sumber
getStuffDone
pembungkus fungsi dan hanya menggunakan literal Janji?catch
blok digetStuffDone
pembungkus antipattern?Promise
contoh asli Anda juga memiliki pembungkus fungsi yang tidak perlu untuk.then
dan.catch
penangan (yaitu bisa saja.then(resolve).catch(reject)
.) Badai sempurna anti-pola.Jawaban:
The antipattern ditangguhkan (sekarang eksplisit-konstruksi antipattern) diciptakan oleh Esailija adalah orang antipattern umum yang baru untuk janji membuat, saya telah membuat sendiri ketika saya pertama kali digunakan janji. Masalah dengan kode di atas adalah bahwa gagal untuk memanfaatkan fakta yang menjanjikan rantai.
Janji dapat dirangkai dengan
.then
dan Anda dapat mengembalikan janji secara langsung. Kode Anda digetStuffDone
dapat ditulis ulang sebagai:Semua janji adalah tentang membuat kode asinkron lebih mudah dibaca dan berperilaku seperti kode sinkron tanpa menyembunyikan fakta itu. Janji merupakan abstraksi atas nilai satu kali operasi, mereka abstrak gagasan pernyataan atau ungkapan dalam bahasa pemrograman.
Anda hanya boleh menggunakan objek yang ditangguhkan saat Anda mengonversi API menjadi janji dan tidak bisa melakukannya secara otomatis, atau saat Anda menulis fungsi agregasi yang lebih mudah diungkapkan dengan cara ini.
Mengutip Esailija:
sumber
.defer()
api ke dalam konstruktor janji yang lebih baru (dan melempar aman), itu tidak (sama sekali) tidak mencemari gagasan membangun janji :)Apakah ada yang salah?
Beruntunglah anda. Sayangnya, mungkin tidak, karena Anda mungkin lupa beberapa tepi case. Dalam lebih dari setengah kejadian yang saya lihat, penulis lupa untuk mengurus penangan kesalahan:
Jika janji lain ditolak, ini akan terjadi tanpa disadari alih-alih disebarkan ke janji baru (di mana janji itu akan ditangani) - dan janji baru itu tetap tertunda selamanya, yang dapat menyebabkan kebocoran.
Hal yang sama terjadi jika kode panggilan balik Anda menyebabkan kesalahan - misalnya ketika
result
tidak memilikiproperty
dan pengecualian dilemparkan. Itu tidak akan ditangani dan meninggalkan janji baru yang belum terselesaikan.Sebaliknya, menggunakan
.then()
tidak secara otomatis menangani kedua skenario ini, dan menolak janji baru ketika terjadi kesalahan:Antipattern yang ditangguhkan tidak hanya rumit, tetapi juga rawan kesalahan . Menggunakan
.then()
untuk chaining jauh lebih aman.Betulkah? Baik. Namun, ini akan sangat rinci dan berlebihan, terutama jika Anda menggunakan perpustakaan janji yang mendukung fitur-fitur lain seperti pembatalan atau pengiriman pesan. Atau mungkin di masa depan, atau Anda ingin menukar perpustakaan Anda dengan yang lebih baik? Anda tidak akan ingin menulis ulang kode Anda untuk itu.
Metode perpustakaan (
then
) tidak hanya mendukung semua fitur secara asli, mereka juga mungkin memiliki optimisasi tertentu. Menggunakannya kemungkinan akan membuat kode Anda lebih cepat, atau setidaknya memungkinkan untuk dioptimalkan oleh revisi perpustakaan di masa depan.Bagaimana saya menghindarinya?
Jadi, setiap kali Anda menemukan diri Anda secara manual membuat
Promise
atauDeferred
dan sudah ada janji yang terlibat, periksa API perpustakaan terlebih dahulu . Antipattern yang ditangguhkan sering diterapkan oleh orang-orang yang melihat janji [hanya] sebagai pola pengamat - tetapi janji lebih dari sekadar panggilan balik : mereka seharusnya dapat dikomposasikan. Setiap perpustakaan yang layak memiliki banyak fungsi yang mudah digunakan untuk komposisi janji-janji dalam setiap cara yang dapat dipikirkan, mengurus semua hal tingkat rendah yang tidak ingin Anda tangani.Jika Anda menemukan kebutuhan untuk menyusun beberapa janji dengan cara baru yang tidak didukung oleh fungsi pembantu yang ada, menulis fungsi Anda sendiri dengan Deferred yang tidak dapat dihindari harus menjadi pilihan terakhir Anda. Pertimbangkan beralih ke perpustakaan yang lebih berfitur, dan / atau ajukan bug pada perpustakaan Anda saat ini. Pemeliharanya harus dapat memperoleh komposisi dari fungsi yang ada, menerapkan fungsi pembantu baru untuk Anda dan / atau membantu mengidentifikasi kasus tepi yang perlu ditangani.
sumber
setTimeout
, di mana konstruktor dapat digunakan tetapi tidak dianggap "Janji anorpattern konstruktor"?setTimeout
", tetapi " fungsisetTimeout
itu sendiri ".setTimeout
", tapi" fungsisetTimeout
itu sendiri "" Bisakah menggambarkan, tautan ke perbedaan, di antara keduanya?setTimeout
jelas berbeda dari fungsisetTimeout
itu sendiri , bukan?