Janji JavaScript: Panduan Definitif, Bagian 1

Blog

Model konkurensi berbasis loop peristiwa tunggal dari JavaScript berurusan dengan pemrosesan peristiwa menggunakan apa yang disebut model I/O non-pemblokiran asinkron. Tidak seperti bahasa komputer seperti Java, di mana peristiwa ditangani menggunakan utas tambahan dan diproses secara paralel dengan utas eksekusi utama, kode JavaScript dieksekusi secara berurutan. Untuk mencegah pemblokiran utas utama pada operasi terikat-I/O, JavaScript menggunakan mekanisme panggilan balik di mana operasi asinkron menentukan panggilan balik – fungsi yang akan dijalankan ketika hasil operasi asinkron sudah siap; sementara aliran kontrol kode terus dijalankan.

Kapan pun kita ingin menggunakan hasil panggilan balik untuk membuat panggilan asinkron lainnya, kita perlu membuat panggilan balik. Karena operasi I/O dapat mengakibatkan kesalahan, kita perlu menangani kesalahan untuk setiap panggilan balik sebelum memproses hasil yang berhasil. Kebutuhan untuk melakukan penanganan kesalahan dan harus menyematkan panggilan balik membuat kode panggilan balik sulit dibaca. Terkadang ini disebut sebagai neraka panggilan balik JavaScript.

Untuk mengatasi masalah ini, JavaScript menawarkan mekanisme yang disebut Promise. Ini adalah paradigma pemrograman umum (lebih lanjut tentangnya di sini: https://en.wikipedia.org/wiki/Futures_and_promises ) dan TC39 memperkenalkannya di ECMAScript 2015. JavaScript Promise adalah objek yang memegang status, yang mewakili penyelesaian (atau kegagalan) akhirnya dari operasi asinkron dan nilai yang dihasilkannya.

Janji baru ada di tertunda negara. Jika Janji berhasil, itu dimasukkan ke dalam terselesaikan nyatakan sebaliknya ditolak . Alih-alih menggunakan mekanisme panggilan balik asli, kode yang menggunakan Promises membuat objek Promise. Kami menggunakan Janji biasanya dengan dua penangan panggilan balik – terselesaikan dipanggil ketika operasi berhasil dan ditolak dipanggil setiap kali terjadi kesalahan.

// Converting a callback based method to a method that returns Promise const fs = require('fs') const readTextFromFile = new Promise((resolve, reject) => { fs.readFile('file.txt', (err, data) => { if (err) { return reject(err) } resolve(data) }) }) // Usage of a method that returns Promise readTextFromFile() .then(data => console.log(data)) .catch(e => console.log(e))

Proses.nextTick(panggilan balik)

Untuk memahami cara kerja Promises di Node.js, penting untuk meninjau cara |_+_| bekerja di Node.js, karena keduanya sangat mirip. |_+_| adalah metode yang menambahkan panggilan balik ke antrian centang berikutnya. Tugas dalam antrian dieksekusi setelah operasi saat ini di lingkaran acara dilakukan dan sebelum loop acara diizinkan untuk melanjutkan. Sederhananya, ada antrian lain di samping loop acara yang dapat kita gunakan untuk menjadwalkan acara. Antrean ini bahkan lebih cepat daripada loop peristiwa dan mungkin terkuras beberapa kali dalam satu centang loop peristiwa.

process.nextTick()

Pada contoh di atas, kita dapat melihat bagaimana |_+_| bekerja dalam praktek. Kami punya dua |_+_| panggilan, dengan panggilan balik segera dijadwalkan dalam loop acara. Kami juga memiliki dua |_+_| metode dengan panggilan balik yang dijadwalkan dalam antrian centang berikutnya. Inilah yang kita lihat di konsol:

Process.nextTick()

Karena kita tahu bahwa antrean centang berikutnya terpisah dari loop peristiwa dan dapat dikuras beberapa kali dalam satu centang loop peristiwa, ini masuk akal. Dua |_+_| callback dieksekusi segera dan dua lainnya |_+_| panggilan balik, diatur dalam loop acara, dieksekusi setelahnya.

Menempatkan begitu banyak panggilan balik dalam antrean centang berikutnya dapat memblokir loop peristiwa dan mencegah operasi I/O apa pun. Itu sebabnya kami memiliki |_+_| yang mewakili jumlah maksimum panggilan balik dalam antrian yang dapat dieksekusi sebelum membiarkan loop peristiwa berlanjut. Nilai defaultnya adalah 1000.

Bagaimana Janji Bekerja?

Janji adalah cara baru dan bagus untuk menangani kode async, tetapi bagaimana cara kerjanya? Untuk memahami manfaat dan karakteristik kinerja Promises, kita perlu memahami bagaimana penerapannya dan apa yang sebenarnya terjadi saat kita kembali |_+_| .

Promise menggunakan antrian Microtask dan dijalankan secara independen dari tugas biasa (callback |_+_|, misalnya). Apa artinya ini? Dalam JavaScript, kami memiliki tiga antrian: (1) loop acara, (2) antrian nextTick dan (3) antrian Microtask. Semua antrian itu bekerja secara independen.

Macrotask adalah tugas reguler yang masuk ke loop peristiwa dan dalam satu centang loop peristiwa, hanya satu Macrotask yang dieksekusi. Microtasks memiliki antrian independen dan, dalam satu centang event-loop, seluruh antrian microtasks dapat dikuras. Ini memberi kami manfaat kinerja yang sangat baik. Pada dasarnya, kami menggunakan tugas mikro ketika kami perlu melakukan hal-hal secara asinkron dengan cara yang sinkron, secepat mungkin.

Janji dieksekusi sebagai Microtasks. Ini berarti bahwa mereka dieksekusi lebih cepat daripada Macrotasks. Mereka tidak pernah dieksekusi secara bersamaan. Microtasks selalu dieksekusi secara berurutan, jadi berbicara tentang paralelisme dengan Janji adalah salah. Mereka bekerja seperti |_+_|, terlepas dari loop acara dalam antrian microtask mereka sendiri.

Macrotasks: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, rendering UI

Microtasks: process.nextTick, Promises, Object.observe, MutationObserver (baca selengkapnya di sini )

const log = msg => () => console.log(`NEXT TICK ${msg}`) const timeout = (time, msg) => { setTimeout(() => { console.log(`TIMEOUT ${msg}`) }, time) } process.nextTick(log('ONE')) timeout(0, 'AFTER-ONE') process.nextTick(log('TWO')) timeout(0, 'AFTER-TWO')

Pada contoh di atas, kode dalam Promise akan dijadwalkan dalam antrian Microtask, tetapi karena tindakan tersebut memerlukan jaringan, maka hanya akan diselesaikan setelah data diterima. Dalam contoh ini, kita akan melihat output ini:

k berarti mengelompokkan python tanpa perpustakaan
process.nextTick

Kami juga perlu menyebutkan bahwa waktu panggilan balik dan Janji dapat sangat bervariasi tergantung pada lingkungan (browser atau Node.js).

Metode Janji

Janji.semua (dapat diubah)

Dibutuhkan serangkaian Janji dan mengembalikan Janji yang dipenuhi ketika semua Janji dalam argumen yang dapat diubah telah dipenuhi atau ditolak segera setelah salah satu Janji ditolak. Jika Janji yang dikembalikan terpenuhi, itu dipenuhi dengan array nilai dari Janji yang dipenuhi dalam urutan yang sama seperti yang didefinisikan dalam argumen array. Jika Janji yang dikembalikan ditolak, itu ditolak dengan alasan dari Janji pertama dalam array yang ditolak. Metode ini dapat berguna untuk menggabungkan hasil dari beberapa Janji.

Kebingungan terbesar tentang Promise.all adalah bahwa Janji yang diteruskan dalam iterable dieksekusi secara bersamaan. |_+_| tidak memberikan paralelisme! Fungsi yang diteruskan dalam konstruktor Promise dieksekusi segera dan Promise diselesaikan dalam antrian microtask. Microtasks selalu dieksekusi secara berurutan.

Metode ini berguna ketika kita ingin menunggu beberapa Janji untuk diselesaikan (atau ditolak) tanpa merantainya secara manual. Kasus penggunaan yang paling umum adalah pemetaan melalui array dan mengembalikan Janji untuk setiap elemen:

instal python linux mint
setTimeout

Penolakan pertama dari Janji akan menyebabkan |_+_| untuk menolak, tetapi Janji konstituen lainnya akan tetap dijalankan. Ini bisa berbahaya karena kita akan menggunakan sumber daya untuk menghasilkan hasil yang tidak akan digunakan.

process.nextTick

Dalam contoh di atas, kami memberikan dua Janji di |_+_|. Yang pertama menunggu satu detik dan kemudian mencatat surat B di konsol. Yang kedua ditolak dengan surat ke . Karena yang kedua ditolak, kami hanya berharap untuk melihat ke di konsol, tetapi Anda akan melihat **a **dan B . Itu karena Anda tidak dapat membatalkan Janji. Setiap Janji yang dijadwalkan akan dieksekusi dan |_+_| hanya membantu kita untuk mengabaikan hasil jika salah satu Janji dalam iterable ditolak, dan sebagai hasilnya memberi kita Janji yang ditolak.

Promise.race(dapat diubah)

Dibutuhkan serangkaian Promise dan mengeksekusinya dengan cara yang sama seperti Promise.all, perbedaannya adalah ia mengembalikan Promise yang memenuhi atau menolak segera setelah salah satu Promise dalam iterable memenuhi atau menolak, dengan nilai atau alasan dari itu Janji. Sebagai contoh, |_+_| dapat digunakan untuk membangun fungsionalitas batas waktu, di mana Janji pertama akan menjadi permintaan HTTP ke beberapa layanan, dan yang kedua akan menjadi fungsi batas waktu. Jika yang kedua gagal terlebih dahulu, Promise yang dihasilkan dari |_+_| akan ditolak dan data dari Janji pertama tidak akan tersedia. Penolakan satu Janji dari iterable tidak akan membatalkan yang lain, mereka akan tetap dieksekusi, seperti pada |_+_| kasus metode.

Next TICK ONE Next TICK TWO TIMEOUT AFTER-ONE TIMEOUT AFTER-TWO

Janji.tolak(alasan)

Mengembalikan objek Janji yang ditolak dengan alasan yang diberikan sebagai argumen. Ini terutama digunakan untuk melempar kesalahan dalam rantai Promise.

Janji.resolve(nilai)

Mengembalikan Janji yang diselesaikan dengan nilai yang diberikan sebagai argumen. Ini terutama digunakan untuk memberikan nilai ke dalam Janji, beberapa objek atau larik, sehingga kita dapat menghubungkannya nanti dengan kode asinkron lainnya.

Tidak sinkron/Menunggu

Tidak sinkron/menunggu semantik ditambahkan di ECMAScript 2017, memungkinkan pemrogram untuk menangani Janji dengan cara yang lebih intuitif. Kata async sebelum suatu fungsi berarti satu hal sederhana: suatu fungsi selalu mengembalikan Janji. Jika kode telah kembali di dalamnya, maka JavaScript secara otomatis membungkusnya menjadi Janji yang diselesaikan dengan nilai itu. Kata kunci |_+_|, yang hanya dapat muncul di dalam |_+_| fungsi, membuat JavaScript menunggu sampai Janji telah diselesaikan dan mengembalikan hasilnya.

Di bawah ini adalah fungsi yang menunggu Janji yang diselesaikan setelah satu detik menggunakan tidak sinkron / menunggu kata kunci:

nextTick

Itu saja untuk Bagian 1! Dengarkan pada hari Senin ketika kita akan membahas kesalahan umum dengan janji.

Awalnya diterbitkan oleh Ivan Jovanovic at https://dzone.com

Belajarlah lagi

Kursus JavaScript Lengkap 2019: Bangun Proyek Nyata!

JavaScript in Action - permainan terbang burung yang menyenangkan dengan DOM

Game Mengemudi Mobil JavaScript dari awal dengan kode sumber

Konsep JavaScript Tingkat Lanjut

Selenium WebDriver - JavaScript nodeJS webdriver IO & lainnya!

Kursus JavaScript Lengkap Untuk Pemula untuk Dikuasai - 2019

Kamp Pelatihan JavaScript Modern (2019)

#javascript

dzone.com

Janji JavaScript: Panduan Definitif, Bagian 1

Jika Anda berurusan dengan Janji dalam Javascript, maka Anda benar-benar perlu membaca panduan ini.