Perbedaan Mendalam: `Promise.all`, `Promise.race`, `Promise.allSettled`, & `Promise.any` dalam JavaScript

Perbedaan Mendalam: `Promise.all`, `Promise.race`, `Promise.allSettled`, & `Promise.any` dalam JavaScript
Dalam dunia JavaScript modern, Promise menjadi fondasi utama untuk menangani operasi asinkron. Mereka membantu kita menghindari "callback hell" yang menakutkan dan menulis kode yang lebih bersih dan mudah dibaca. Namun, dengan berbagai metode yang tersedia untuk mengelola kumpulan Promise, penting untuk memahami perbedaan mendalam antara mereka. Artikel ini akan membahas empat metode penting: Promise.all, Promise.race, Promise.allSettled, dan Promise.any. Kita akan menjelajahi bagaimana masing-masing metode bekerja, kapan menggunakannya, dan perbedaan kunci antara mereka.
Memahami Dasar Promise di JavaScript

Sebelum kita menyelami perbedaan antara metode-metode tersebut, mari kita sedikit mengingat tentang apa itu Promise. Secara sederhana, Promise adalah representasi dari nilai yang mungkin tersedia, mungkin tidak tersedia, atau gagal di masa depan. Mereka memiliki tiga status:
- Pending: Promise sedang dalam proses, menunggu operasi asinkron selesai.
- Fulfilled: Operasi asinkron berhasil, dan Promise memiliki nilai.
- Rejected: Operasi asinkron gagal, dan Promise memiliki alasan kegagalan.
Dengan memahami status ini, kita bisa mulai memahami bagaimana berbagai metode bekerja dalam mengelola kumpulan Promise.
`Promise.all`: Menunggu Kesuksesan Semua Promise

Promise.all adalah mungkin metode yang paling umum digunakan dalam mengelola kumpulan Promise. Metode ini mengambil larik Promise sebagai argumen dan mengembalikan satu Promise. Promise yang dikembalikan ini:
- Akan fulfilled jika dan hanya jika semua Promise dalam larik input fulfilled. Nilai fulfilled-nya adalah larik yang berisi nilai-nilai fulfilled dari setiap Promise dalam urutan yang sama dengan larik input.
- Akan rejected jika setidaknya satu Promise dalam larik input rejected. Alasan rejection-nya adalah alasan rejection dari Promise pertama yang rejected.
Dengan kata lain, Promise.all seperti memiliki mentalitas "semua atau tidak sama sekali". Jika satu saja gagal, semuanya gagal.
Contoh:
```javascript const promise1 = Promise.resolve(1); const promise2 = Promise.resolve(2); const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3]) .then((values) => { console.log(values); // Output: [1, 2, 3] }) .catch((error) => { console.error(error); // Tidak akan terpanggil karena semua Promise berhasil }); ```
Dalam contoh di atas, semua Promise berhasil, sehingga Promise.all fulfilled dengan larik yang berisi nilai 1, 2, dan 3.
Contoh dengan rejection:
```javascript const promise1 = Promise.resolve(1); const promise2 = Promise.reject('Terjadi kesalahan!'); const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3]) .then((values) => { console.log(values); // Tidak akan terpanggil karena ada Promise yang gagal }) .catch((error) => { console.error(error); // Output: Terjadi kesalahan! }); ```
Di sini, promise2 rejected, menyebabkan Promise.all untuk langsung rejected dengan alasan "Terjadi kesalahan!".
Kapan menggunakan `Promise.all`?
Gunakan Promise.all ketika Anda perlu menunggu semua operasi asinkron selesai sebelum melanjutkan. Contohnya, saat Anda perlu mengambil data dari beberapa API sebelum merender komponen UI, atau saat Anda perlu memproses beberapa file secara paralel dan membutuhkan hasil dari semuanya sebelum melakukan langkah selanjutnya.
`Promise.race`: Siapa yang Paling Cepat?

Promise.race, seperti namanya, adalah tentang kecepatan. Metode ini juga mengambil larik Promise sebagai argumen dan mengembalikan satu Promise. Promise yang dikembalikan ini:
- Akan fulfilled atau rejected berdasarkan Promise pertama yang fulfilled atau rejected.
Artinya, Promise.race hanya peduli tentang Promise tercepat untuk selesai, terlepas dari apakah itu berhasil atau gagal. Promise-promise lain diabaikan setelah yang pertama selesai.
Contoh:
```javascript const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'Selesai setelah 500ms')); const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'Selesai setelah 100ms'));
Promise.race([promise1, promise2]) .then((value) => { console.log(value); // Output: Selesai setelah 100ms }) .catch((error) => { console.error(error); // Tidak akan terpanggil karena promise2 berhasil }); ```
Dalam contoh ini, promise2 selesai lebih cepat daripada promise1, sehingga Promise.race fulfilled dengan nilai dari promise2.
Contoh dengan rejection:
```javascript const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'Selesai setelah 500ms')); const promise2 = Promise.reject('Gagal dengan cepat!');
Promise.race([promise1, promise2]) .then((value) => { console.log(value); // Tidak akan terpanggil karena promise2 gagal }) .catch((error) => { console.error(error); // Output: Gagal dengan cepat! }); ```
Di sini, promise2 rejected terlebih dahulu, sehingga Promise.race rejected dengan alasan rejection dari promise2.
Kapan menggunakan `Promise.race`?
Gunakan Promise.race ketika Anda hanya tertarik pada hasil tercepat dari beberapa operasi asinkron. Contohnya, saat Anda ingin menerapkan timeout pada permintaan API. Anda bisa membuat Promise yang akan rejected setelah waktu tertentu, dan menggunakannya dalam Promise.race bersama dengan Promise untuk permintaan API. Jika API membutuhkan waktu terlalu lama, Promise timeout akan "memenangkan perlombaan" dan menolak permintaan.
`Promise.allSettled`: Tidak Ada yang Tertinggal

Promise.allSettled adalah metode yang lebih toleran daripada Promise.all. Metode ini juga mengambil larik Promise sebagai argumen dan mengembalikan satu Promise yang selalu fulfilled. Promise yang dikembalikan ini:
- Akan fulfilled setelah semua Promise dalam larik input telah settled (fulfilled atau rejected). Nilai fulfilled-nya adalah larik objek, yang masing-masing menggambarkan hasil dari setiap Promise input.
Setiap objek dalam larik hasil memiliki dua properti:
- `status`: String yang menunjukkan apakah Promise fulfilled (`'fulfilled'`) atau rejected (`'rejected'`).
- `value` (jika `status` adalah `'fulfilled'`): Nilai fulfilled dari Promise.
- `reason` (jika `status` adalah `'rejected'`): Alasan rejection dari Promise.
Promise.allSettled sangat berguna ketika Anda ingin tahu hasil dari setiap Promise, terlepas dari apakah mereka berhasil atau gagal. Ini sangat penting ketika kegagalan satu Promise tidak boleh menghentikan seluruh proses.
Contoh:
```javascript const promise1 = Promise.resolve(1); const promise2 = Promise.reject('Terjadi kesalahan!'); const promise3 = Promise.resolve(3);
Promise.allSettled([promise1, promise2, promise3]) .then((results) => { console.log(results); // Output: // [ // { status: 'fulfilled', value: 1 }, // { status: 'rejected', reason: 'Terjadi kesalahan!' }, // { status: 'fulfilled', value: 3 } // ] }); ```
Perhatikan bahwa Promise.allSettled selalu fulfilled, dan larik `results` berisi informasi tentang keberhasilan dan kegagalan setiap Promise.
Kapan menggunakan `Promise.allSettled`?
Gunakan Promise.allSettled ketika Anda perlu tahu hasil dari semua Promise, terlepas dari apakah mereka berhasil atau gagal. Contohnya, saat Anda mengirimkan data ke beberapa server secara paralel dan ingin mencatat semua keberhasilan dan kegagalan, atau saat Anda ingin menampilkan pesan kesalahan yang berbeda untuk setiap operasi yang gagal.
`Promise.any`: Yang Penting Ada yang Berhasil

Promise.any adalah metode yang sedikit lebih baru dibandingkan yang lain. Metode ini juga mengambil larik Promise sebagai argumen dan mengembalikan satu Promise. Promise yang dikembalikan ini:
- Akan fulfilled dengan nilai dari Promise pertama yang fulfilled.
- Akan rejected dengan
AggregateErrorjika semua Promise dalam larik input rejected.AggregateErrorberisi larik yang berisi semua alasan rejection.
Dengan kata lain, Promise.any hanya peduli tentang keberhasilan. Jika ada satu saja Promise yang berhasil, maka Promise.any akan fulfilled dengan nilai dari Promise tersebut. Jika semua Promise gagal, maka Promise.any akan rejected dengan AggregateError.
Contoh:
```javascript const promise1 = Promise.reject('Gagal 1'); const promise2 = Promise.resolve(2); const promise3 = Promise.reject('Gagal 3');
Promise.any([promise1, promise2, promise3]) .then((value) => { console.log(value); // Output: 2 }) .catch((error) => { console.error(error); // Tidak akan terpanggil karena promise2 berhasil }); ```
Dalam contoh ini, promise2 fulfilled, sehingga Promise.any fulfilled dengan nilai 2.
Contoh dengan rejection semua Promise:
```javascript const promise1 = Promise.reject('Gagal 1'); const promise2 = Promise.reject('Gagal 2'); const promise3 = Promise.reject('Gagal 3');
Promise.any([promise1, promise2, promise3]) .then((value) => { console.log(value); // Tidak akan terpanggil karena semua Promise gagal }) .catch((error) => { console.error(error); // Output: AggregateError: All Promises rejected console.log(error.errors); // Output: ['Gagal 1', 'Gagal 2', 'Gagal 3'] }); ```
Di sini, semua Promise rejected, sehingga Promise.any rejected dengan AggregateError, yang berisi alasan rejection dari setiap Promise.
Kapan menggunakan `Promise.any`?
Gunakan Promise.any ketika Anda hanya membutuhkan setidaknya satu operasi asinkron untuk berhasil. Contohnya, saat Anda mencoba mengambil data dari beberapa sumber yang berbeda, dan Anda cukup puas jika salah satu sumber berhasil memberikan data. Atau, saat Anda ingin mencoba beberapa metode autentikasi yang berbeda, dan Anda cukup puas jika salah satu metode berhasil mengotentikasi pengguna.
Ringkasan Perbedaan Kunci
Untuk mempermudah pemahaman, berikut adalah ringkasan perbedaan kunci antara keempat metode:
| Metode | Behavior jika semua berhasil | Behavior jika setidaknya satu gagal | Nilai yang dikembalikan | Kapan Digunakan |
|---|---|---|---|---|
Promise.all | Fulfilled dengan larik nilai | Rejected dengan alasan Promise pertama yang gagal | Satu Promise | Ketika semua operasi harus berhasil |
Promise.race | Fulfilled dengan nilai Promise tercepat | Rejected dengan alasan Promise tercepat yang gagal | Satu Promise | Ketika hanya membutuhkan hasil tercepat, terlepas dari keberhasilan atau kegagalan |
Promise.allSettled | Fulfilled dengan larik objek (status & nilai/alasan) | Fulfilled dengan larik objek (status & nilai/alasan) | Satu Promise (selalu fulfilled) | Ketika membutuhkan hasil dari semua operasi, terlepas dari keberhasilan atau kegagalan |
Promise.any | Fulfilled dengan nilai Promise pertama yang berhasil | Rejected dengan AggregateError (jika semua gagal) | Satu Promise | Ketika membutuhkan setidaknya satu operasi untuk berhasil |
Kesimpulan
Memahami perbedaan antara Promise.all, Promise.race, Promise.allSettled, dan Promise.any adalah kunci untuk menulis kode JavaScript yang efisien dan efektif. Dengan memilih metode yang tepat untuk setiap skenario, Anda dapat mengoptimalkan performa aplikasi Anda, menangani kesalahan dengan lebih baik, dan membuat kode Anda lebih mudah dibaca dan dipelihara. Semoga artikel ini membantu Anda memahami perbedaan mendalam antara metode-metode ini dan memberikan Anda wawasan untuk menggunakannya dengan lebih efektif dalam proyek-proyek JavaScript Anda. Selamat mencoba!
Posting Komentar untuk "Perbedaan Mendalam: `Promise.all`, `Promise.race`, `Promise.allSettled`, & `Promise.any` dalam JavaScript"
Posting Komentar