Saat melakukan pemrograman asinkron single-threaded, ada dua teknik utama yang saya kenal. Yang paling umum adalah menggunakan callback. Itu berarti meneruskan ke fungsi yang bertindak secara tidak sinkron sebagai fungsi panggil balik sebagai parameter. Ketika operasi asinkron akan selesai, panggilan balik akan dipanggil.
Beberapa jQuery
kode tipikal dirancang dengan cara ini:
$.get('userDetails', {'name': 'joe'}, function(data) {
$('#userAge').text(data.age);
});
Namun jenis kode ini bisa menjadi berantakan dan sangat bersarang ketika kita ingin membuat panggilan async tambahan satu demi satu ketika yang sebelumnya selesai.
Jadi pendekatan kedua menggunakan Janji. Janji adalah sebuah objek yang mewakili nilai yang mungkin belum ada. Anda dapat mengatur callback di atasnya, yang akan dipanggil ketika nilainya siap dibaca.
Perbedaan antara Janji dan pendekatan panggilan balik tradisional, adalah bahwa metode async sekarang secara sinkron mengembalikan objek Janji, di mana klien mengaktifkan panggilan balik. Misalnya, kode serupa menggunakan Janji di AngularJS:
$http.get('userDetails', {'name': 'joe'})
.then(function(response) {
$('#userAge').text(response.age);
});
Jadi pertanyaan saya adalah: apakah sebenarnya ada perbedaan nyata? Perbedaannya tampaknya murni sintaksis.
Apakah ada alasan yang lebih dalam untuk menggunakan satu teknik di atas yang lain?
Jawaban:
Adalah adil untuk mengatakan bahwa janji hanyalah gula sintaksis. Segala sesuatu yang dapat Anda lakukan dengan janji yang dapat Anda lakukan dengan panggilan balik. Bahkan, sebagian besar implementasi janji memberikan cara untuk mengkonversi antara keduanya kapan pun Anda inginkan.
Alasan mendalam mengapa janji sering kali lebih baik adalah bahwa mereka lebih tenang , yang secara kasar berarti bahwa menggabungkan beberapa janji "hanya berfungsi", sementara menggabungkan beberapa panggilan balik sering kali tidak. Sebagai contoh, itu sepele untuk menetapkan janji ke variabel dan melampirkan penangan tambahan untuk nanti, atau bahkan melampirkan penangan ke sekelompok besar janji yang dieksekusi hanya setelah semua janji selesai. Meskipun Anda dapat mengemulasi hal-hal ini dengan callback, dibutuhkan lebih banyak kode, sangat sulit untuk dilakukan dengan benar, dan hasil akhirnya biasanya jauh lebih tidak dapat dipertahankan.
Salah satu cara terbesar (dan paling halus) yang dijanjikan mendapatkan kompabilitas mereka adalah dengan penanganan nilai pengembalian yang sama dan pengecualian yang tidak tertangkap. Dengan panggilan balik, bagaimana pengecualian ditangani mungkin sepenuhnya bergantung pada mana dari banyak panggilan balik bersarang yang melemparkannya, dan fungsi mana yang menerima panggilan balik yang memiliki coba / tangkap dalam implementasinya. Dengan janji, Anda tahu bahwa pengecualian yang lolos dari satu fungsi panggilan balik akan ditangkap dan diteruskan ke penangan kesalahan yang Anda berikan
.error()
atau.catch()
.Misalnya, Anda memberikan satu panggilan balik versus satu janji, memang benar tidak ada perbedaan yang signifikan. Justru ketika Anda memiliki miliaran panggilan balik versus satu miliar janji, kode berbasis janji cenderung terlihat jauh lebih baik.
Berikut adalah upaya pada beberapa kode hipotetis yang ditulis dengan janji dan kemudian dengan panggilan balik yang seharusnya cukup kompleks untuk memberi Anda beberapa gagasan tentang apa yang saya bicarakan.
Dengan Janji:
Dengan Callback:
Mungkin ada beberapa cara pintar untuk mengurangi duplikasi kode dalam versi callback bahkan tanpa janji, tetapi semua yang saya bisa pikirkan untuk menerapkan sesuatu yang sangat menjanjikan.
sumber
yield
janji-janji. Keuntungan di sini adalah bahwa Anda mendapatkan kemampuan untuk mencampur dalam struktur aliran kontrol asli, yang dapat bervariasi dalam berapa banyak operasi async yang mereka lakukan. Saya akan menambahkan versi yang menunjukkan ini.then(callback)
metode pada Janji yang menerima panggilan balik (bukan metode pada API yang menerima panggilan balik ini) tidak harus melakukan apa pun dengan IoC. Promise memperkenalkan satu tingkat tipuan yang berguna untuk komposisi, rantai, dan penanganan kesalahan (pemrograman berorientasi kereta api pada dasarnya), tetapi panggilan balik masih tidak dilakukan oleh klien, jadi tidak benar-benar tidak adanya IoC.