7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. JavaScript

A Primer ES7 Async fungsi

Scroll to top
Read Time: 11 mins

Indonesian (Bahasa Indonesia) translation by Dendi Deden (you can also view the original English article)

Jika Anda sudah mengikuti dunia JavaScript, Anda mungkin pernah mendengar tentang Promise. Ada beberapa tutorial yang besar secara online jika Anda ingin belajar tentang Promise, tapi aku tidak akan menjelaskan mereka di sini; Artikel ini mengasumsikan Anda telah memiliki pengetahuan tentang Promise.

Promise yang disebut-sebut sebagai masa depan pemrograman JavaScript asynchronous. Promise benar-benar bagus dan membantu memecahkan banyak masalah yang timbul dengan pemrograman asynchronous, tetapi yang mengklaim hanya agak benar. Pada kenyataannya, pronise adalah dasar dari masa depan pemrograman JavaScript asynchronous. Idealnya, Promise akan terselip di balik layar dan kami akan dapat menulis kode asynchronous kita seolah-olah synchronous.

di ECMAScript 7, ini akan menjadi lebih dari mimpi aneh: itu akan menjadi kenyataan, dan aku akan menunjukkan kepada Anda bahwa realitas — disebut async fungsi — sekarang. Mengapa kita berbicara tentang ini sekarang? Setelah semua, ES6 belum bahkan benar-benar selesai, jadi siapa yang tahu berapa lama itu akan sebelum kita melihat ES7. Kebenaran adalah Anda dapat menggunakan teknologi ini sekarang, dan pada akhir posting ini, saya akan menunjukkan Anda bagaimana.

Keadaan saat ini

Sebelum saya mulai menunjukkan cara menggunakan fungsi async, saya ingin pergi melalui beberapa contoh dengan Promise (menggunakan Promse ES6). Kemudian, saya akan mengkonversi contoh-contoh ini menggunakan fungsi async sehingga Anda dapat melihat perbedaan besar yang dibuat.

Contoh

Untuk contoh pertama kami, kami akan melakukan sesuatu yang benar-benar sederhana: memanggil fungsi yang asynchronous dan logging nilai kembalian.

Sekarang bahwa kita memiliki contoh dasar didefinisikan, mari kita melompat menjadi sesuatu yang sedikit lebih rumit. Aku akan menggunakan dan memodifikasi contoh dari posting di blog saya sendiri yang pergi melalui beberapa pola untuk menggunakan promise dalam skenario yang berbeda. Setiap contoh asynchronously mengambil sebuah array nilai, melakukan operasi asynchronous yang berubah setiap nilai dalam array, log setiap nilai baru dan akhirnya mengembalikan array penuh dengan nilai-nilai baru.

Pertama, kita akan melihat contoh yang akan menjalankan beberapa operasi asynchronous secara paralel, dan kemudian menanggapi mereka segera sebagai masing selesai, terlepas dari urutan di mana mereka selesai. getValues fungsi yang sama dari contoh sebelumnya. fungsi asyncOperation juga digunakan kembali dalam contoh-contoh yang akan datang.

Kita dapat melakukan hal yang sama persis, tapi pastikan logging yang terjadi dalam urutan elemen dalam array. Dengan kata lain, contoh ini berikutnya akan melakukan bekerja asynchronous secara paralel, tapi pekerjaan synchronous akan berurutan:

Contoh terakhir akan menunjukkan pola yang mana kita menunggu operasi asynchronous sebelumnya untuk menyelesaikan sebelum memulai berikutnya. Tidak ada yang berjalan secara paralel dalam contoh ini; segala sesuatu berurutan.

Bahkan dengan kemampuan Promise untuk mengurangi callback nesting, itu benar-benar tidak membantu banyak. Menjalankan sejumlah pemanggilan asynchronous berurutan akan berantakan tidak peduli apa yang Anda lakukan. Hal ini terutama mengerikan untuk melihat semua kata kunci return bersarang. Jika kami memasukan array newValues melalui promise dalam reduce callback daripada membuat global untuk fungsi seluruh foo, kita harus menyesuaikan kode untuk memiliki kembalian bahkan lebih bersarang, seperti ini:

Jangan Anda setuju kita perlu untuk memperbaiki hal ini? Mari kita lihat solusi.

Async fungsi datang untuk menyelamatkan

Bahkan dengan promise, pemrograman asynchronous tidak persis sederhana dan tidak selalu beraliran baik dari A sampai Z. Synchronous  pemrograman jauh lebih sederhana dan menulis dan membaca jauh lebih alami. Spesifikasi Async fungsi terlihat menjadi sarana (menggunakan ES6 generator di belakang layar) untuk menulis kode Anda seolah-Synchronous .

Bagaimana kita menggunakan mereka?

Hal pertama yang perlu kita lakukan adalah awalan fungsi kita dengan kata kunci async. Tanpa kata kunci ini di tempat, kita tidak dapat menggunakan semua await kata kunci di dalam fungsi, yang saya akan menjelaskannya sedikit.

Kata kunci async tidak hanya memungkinkan kita untuk menggunakan await, itu juga memastikan bahwa fungsi akan mengembalikan sebuah objek Promise. Dalam fungsi async, setiap kali Anda mengembalikan nilai, fungsi akan benar-benar kembali Promise yang diselesaikan dengan nilai tersebut. Cara menolak adalah untuk melempar kesalahan, di mana kasus nilai penolakan akan objek kesalahan. Berikut adalah contoh sederhana:

Kami bahkan belum sampai bagian terbaik dan kami sudah membuat kode kita lebih seperti sinkron kode karena kami tidak mampu menghentikan secara eksplisit main-main dengan objek Promise. Kita dapat mengambil fungsi apapun dan membuatnya mengembalikan sebuah objek Promise hanya dengan menambahkan kata kunci async ke depan itu.

Mari kita pergi ke depan dan mengkonversi getValues dan asyncOperation fungsi:

Mudah! Sekarang, mari kita lihat di bagian terbaik dari semua: await kata kunci. Dalam fungsi async Anda, setiap kali Anda melakukan suatu operasi yang mengembalikan promise, Anda dapat throw await kata kunci di depannya, dan itu akan menghentikan sisa fungsi sampai promise dikembalikan telah diselesaikan atau atau ditolak.. Pada saat itu, await promisingOperation() akan mengevaluasi nilai diselesaikan atau ditolak. Sebagai contoh:

Ketika Anda memanggil foo, itu akan menunggu sampai menyelesaikan promisingOperation dan kemudian itu akan logout "Success!" pesan, atau promisingOperation akan ditolak, dalam hal penolakan akan dimasukan dan foo akan menolak dengan "Failure!". Karena foo tidak mengembalikan apa-apa, itu akan menyelesaikan dengan asumsi undefined promisingOperation sukses.

Ada hanya satu pertanyaan yang tersisa: bagaimana kita menyelesaikan kegagalan? Jawaban untuk pertanyaan itu sederhana: semua yang perlu kita lakukan adalah dibungkus dalam try... catch blok. Jika salah satu operasi asynchronous ditolak, kita dapat menangkap itu dan menanganinya:

Sekarang bahwa kita telah menekan pada semua dasar-dasar, mari kita pergi melalui contoh promise kami sebelumnya dan mengkonversi mereka untuk menggunakan fungsi async.

Contoh

Contoh pertama di atas dibuat getValues dan menggunakannya. Kami telah kembali membuat getValues sehingga kita hanya perlu membuat ulang kode untuk menggunakannya. Ada satu peringatan yang potensial untuk async fungsi yang muncul di sini: kode akan dibutuhkan dalam fungsi. Contoh sebelumnya adalah di global scope (sejauh yang siapa pun bisa tahu), tetapi kita perlu untuk membungkus kode async kami dalam fungsi async untuk mendapatkannya bekerja:

Bahkan dengan pembungkus kode dalam fungsi, aku masih mengklaim lebih mudah dibaca dan memiliki lebih sedikit byte (jika Anda menghapus komentar). Contoh kami berikutnya, jika Anda ingat, melakukan segala sesuatu secara paralel. Ini sedikit rumit, karena kami memiliki inner fungsi yang perlu mengembalikan promise. Jika kita menggunakan kata kunci await dalam inner fungsi, fungsi yang juga perlu diawali dengan async.

Anda mungkin telah memperhatikan asterisk terpasang  await kata kunci terakhir. Hal ini tampaknya masih diperdebatkan sedikit, tapi kelihatannya seperti await* akan pada dasarnya auto-wrap ekspresi untuk berdiri di Promise.all. Sekarang, walaupun, tool kita akan melihat di kemudian tidak mendukung await*, jadi itu harus dikonversi ke await Promise.all(newValues); seperti yang kita lakukan dalam contoh berikutnya.

Contoh berikutnya akan menjalankan panggilan asyncOperation secara paralel, tapi akan kemudian membawa itu semua kembali bersama-sama dan melakukan output secara berurutan.

Saya suka itu. Itulah sangat bersih. Jika kita menghapus await dan async kata kunci, menghapus Promise.all wrapper, dan membuat getValues dan asyncOperation synchronous, maka kode ini akan masih bekerja dengan cara yang sama persis kecuali bahwa itu akan synchronous. Ini pada dasarnya apa yang kami bertujuan untuk dicapai.

Contoh terakhir akan, tentu saja, memiliki segalanya berjalan secara berurutan. Tidak ada operasi asynchronous dilakukan sampai sebelumnya selesai.

Sekali lagi, kami membuat async inner fungsi. Ada quirk menarik yang terungkap dalam kode ini. Saya memasukan [] di sebagai "memo" nilai untuk reduce, tapi kemudian saya menggunakan await di atasnya. Nilai await tidak diperlukan untuk promise. Ini dapat mengambil nilai apapun, dan jika tidak promise, itu tidak akan menunggu untuk itu; itu akan hanya menjalankan serentak. Tentu saja, meskipun, setelah pertama pelaksanaan panggilan balik, kami akan benar-benar bekerja dengan promise.

Contoh ini cukup banyak persis seperti contoh pertama, kecuali bahwa kita menggunakan reduce daripada map sehingga kita dapat await operasi sebelumnya, dan kemudian karena kami menggunakan reduce untuk membangun sebuah array (bukan sesuatu yang Anda biasanya lakukan, terutama jika Anda sedang membangun berbagai ukuran yang sama sebagai array original), kita perlu membangun array dalam callback untuk reduce.

Menggunakan fungsi Async hari ini

Sekarang bahwa Anda mendapatkan sekilas tentang kesederhanaan dan keangkeran async fungsi, Anda mungkin menangis seperti saya lakukan pertama kali aku melihat mereka. Aku tidak menangis keluar dari sukacita (meskipun saya hampir melakukan); tidak, saya menangis karena ES7 tidak akan di sini sampai aku mati! Pada setidaknya itulah yang saya rasakan. Kemudian saya menemukan tentang Traceur.

Traceur ini ditulis dan dikelola oleh Google. Ini adalah transpiler yang mengubah kode ES6 untuk ES5. Itu tidak membantu! Yah, itu tidak, kecuali mereka juga menerapkan dukungan untuk async fungsi. Hal ini masih fitur percobaan, yang berarti Anda akan perlu memberitahukan secara eksplisit kompilator Anda menggunakan fitur itu, dan bahwa Anda pasti ingin menguji kode Anda secara menyeluruh untuk memastikan tidak ada masalah dengan kompilasi.

Menggunakan compiler seperti Traceur berarti bahwa Anda akan memiliki beberapa sedikit bengkak, jelek kode yang dikirim ke klien, yang tidak apa yang Anda inginkan, tetapi jika Anda menggunakan sumber maps, ini pada dasarnya menghilangkan sebagian besar kerugian yang terkait dengan pengembangan. Anda akan membaca, menulis, dan debugging bersih ES6/7 kode, daripada harus membaca, menulis, dan debug kekacauan rumit dari kode yang perlu bekerja di sekitar keterbatasan bahasa.

Tentu saja, ukuran kode masih akan lebih besar daripada jika Anda telah menuis tangan kode ES5 (kemungkinan besar), jadi Anda mungkin perlu untuk menemukan beberapa jenis keseimbangan antara kode maintainable dan performant kode, tapi itu adalah keseimbangan Anda sering perlu untuk menemukan bahkan tanpa menggunakan transpiler.

Menggunakan Traceur

Traceur adalah sebuah utilitas command line yang dapat diinstal melalui NPM:

Secara umum, Traceur ini cukup mudah digunakan, tetapi beberapa pilihan yang dapat membingungkan dan mungkin memerlukan beberapa eksperimen. Anda dapat melihat daftar pilihan untuk rincian lebih lanjut. Yang kita benar-benar tertarik adalah opsi --experimental.

Anda perlu gunakan pilihan ini untuk mengaktifkan fitur eksperimental, yang adalah bagaimana kita bisa async fungsi untuk bekerja. Setelah Anda memiliki file JavaScript (main.js dalam kasus ini) dengan ES6 kode dan async fungsi termasuk, Anda hanya dapat kompilasi dengan ini:

Anda juga hanya dapat menjalankan kode dengan menghilangkan --out compiled.js. Anda tidak akan melihat banyak kecuali kode memiliki pernyataan console.log (atau output konsol lain), tapi setidaknya, Anda dapat memeriksa kesalahan. Anda mungkin ingin menjalankan itu dalam browser, meskipun. Jika ini terjadi, ada beberapa langkah Anda perlu untuk diambil.

  1. Download script traceur-runtime.js. Ada banyak cara untuk mendapatkannya, tapi salah satu yang paling mudah adalah dari NPM: npm install traceur-runtime. File tersebut kemudian akan tersedia sebagai index.js dalam folder modul tersebut.
  2. Dalam file HTML Anda, menambahkan tag script yang menarik dalam Traceur Runtime Script.
  3. Menambahkan tag script lain di bawah Traceur Runtime Script untuk menarik compiled.js.

Setelah ini, kode Anda harusnya berjalan!

Mengotomatisasi Traceur kompilasi

Selain hanya menggunakan tool command line Traceur, Anda juga dapat mengotomatisasi kompilasi sehingga Anda tidak perlu terus kembali ke konsol Anda dan kembali menjalankan kompilator. Grunt dan Gulp, adalah otomatis task runner, masing-masing memiliki sendiri plugin yang dapat Anda gunakan untuk mengotomatisasi Traceur kompilasi: grunt-traceur dan gulp-traceur masing-masing.

Masing-masing task runner ini dapat mengatur untuk menonton sistem file Anda dan kompilasi ulang kode instan Anda menyimpan perubahan ke file JavaScript Anda. Untuk mempelajari cara menggunakan Grunt atau Gulp, Periksa dokumentasi "Getting Started" mereka.

Kesimpulan

ES7's async fungsi menawarkan pengembang cara untuk benar-benar keluar dari callback hell yang menjanjikan tidak pernah bisa mereka sendiri. Fitur baru ini memungkinkan kita untuk menulis kode asynchronous dengan cara yang sangat mirip dengan kode synchronous, dan meskipun ES6 masih menunggu rilis penuh, kita sudah dapat menggunakan fungsi async hari ini melalui transpilation. Apa yang Anda tunggu? Pergi keluar dan membuat kode Anda yang mengagumkan!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.