|
| 1 | +# Fetch: Membatalkan |
1 | 2 |
|
2 | | -# Fetch: Abort |
| 3 | +Seperti yang kita tahu, `fetch` mengembalikan `promise` dan Javascript secara umum tidak memiliki konsep untuk "membatalkan" sebuah janji (`Promise`). Jadi, bagaimana kita bisa membatalkan `fetch` yang sedang dijalankan? misalnya, jika tindakan pengguna pada situs kita mengindikasikan bahwa `fetch` sudah tidak dibutuhkan lagi. |
3 | 4 |
|
4 | | -As we know, `fetch` returns a promise. And JavaScript generally has no concept of "aborting" a promise. So how can we cancel an ongoing `fetch`? E.g. if the user actions on our site indicate that the `fetch` isn't needed any more. |
| 5 | +Terdapat objek bawaan khusus untuk tujuan ini: `AbortContoller`. Metode tersebut dapat digunakan untuk membatalkan tidak hanya `fetch`, tetapi tugas asingkron lainnya. |
5 | 6 |
|
6 | | -There's a special built-in object for such purposes: `AbortController`. It can be used to abort not only `fetch`, but other asynchronous tasks as well. |
| 7 | +Penggunaannya sangat mudah: |
7 | 8 |
|
8 | | -The usage is very straightforward: |
| 9 | +## Objek AbortController |
9 | 10 |
|
10 | | -## The AbortController object |
11 | | - |
12 | | -Create a controller: |
| 11 | +Membuat sebuah pengontrol (_controller_) |
13 | 12 |
|
14 | 13 | ```js |
15 | 14 | let controller = new AbortController(); |
16 | 15 | ``` |
17 | 16 |
|
18 | | -A controller is an extremely simple object. |
| 17 | +Pengontrol adalah objek yang sangat sederhana. |
| 18 | + |
| 19 | +- Hanya memiliki satu metode `abort()`, |
| 20 | +- dan sebuah properti `signal` yang memungkinkan untuk menyetel `listener` pada objek pengontrol. |
19 | 21 |
|
20 | | -- It has a single method `abort()`, |
21 | | -- And a single property `signal` that allows to set event liseners on it. |
| 22 | +Ketika `abort()` dipanggil: |
22 | 23 |
|
23 | | -When `abort()` is called: |
24 | | -- `controller.signal` emits the `"abort"` event. |
25 | | -- `controller.signal.aborted` property becomes `true`. |
| 24 | +- `contoller.signal` mengeluarkan _event_ `"abort"` |
| 25 | +- Properti `controller.signal.aborted` menjadi bernilai `true` |
26 | 26 |
|
27 | | -Generally, we have two parties in the process: |
28 | | -1. The one that performs an cancelable operation, it sets a listener on `controller.signal`. |
29 | | -2. The one one that cancels: it calls `controller.abort()` when needed. |
| 27 | +Secara Umum, kita memiliki dua pihak dalam prosesnya: |
30 | 28 |
|
31 | | -Here's the full example (without `fetch` yet): |
| 29 | +1. Satu pihak yang melaksanakan tindakan terntentu ketika operasi dibatalkan, itu menyetel _listener_ pada `controller.signal`. |
| 30 | +2. Satu pihak lainnya yang membatalkan: itu memanggil `controller.abort()` ketika diperlukan. |
| 31 | + |
| 32 | +Berikut contoh lengkapnya (tanpa `fetch`) |
32 | 33 |
|
33 | 34 | ```js run |
34 | 35 | let controller = new AbortController(); |
35 | 36 | let signal = controller.signal; |
36 | 37 |
|
37 | | -// The party that performs a cancelable operation |
38 | | -// gets "signal" object |
39 | | -// and sets the listener to trigger when controller.abort() is called |
40 | | -signal.addEventListener('abort', () => alert("abort!")); |
| 38 | +// Pihak yang melakukan tindakan tertentu ketika operasi dibatalkan |
| 39 | +// mendapatkan objek "signal" |
| 40 | +// dan menyetel 'listener' untuk memicu ketika controller.abort() dipanggil |
| 41 | +signal.addEventListener('abort', () => alert('abort!')); |
41 | 42 |
|
42 | | -// The other party, that cancels (at any point later): |
43 | | -controller.abort(); // abort! |
| 43 | +// Pihak lain yang membatalkan (penjelasnnya nanti) |
| 44 | +controller.abort(); // gagalkan! |
44 | 45 |
|
45 | | -// The event triggers and signal.aborted becomes true |
| 46 | +// Pemicu 'event' dan nilai 'signal.aborted' menjadi 'true' |
46 | 47 | alert(signal.aborted); // true |
47 | 48 | ``` |
48 | 49 |
|
49 | | -As we can see, `AbortController` is just a means to pass `abort` events when `abort()` is called on it. |
| 50 | +Seperti yang kita lihat, `AbortController` hanyalah sarana untuk meneruskan _event_ `abort()` ketika dipanggil. |
50 | 51 |
|
51 | | -We could implement same kind of event listening in our code on our own, without `AbortController` object at all. |
| 52 | +Kita dapat mengimplementasikan jenis _event listener_ yang sama pada kode kita, walaupun tanpa objek `AbortController` sama sekali. |
52 | 53 |
|
53 | | -But what's valuable is that `fetch` knows how to work with `AbortController` object, it's integrated with it. |
| 54 | +Tetapi yang berharga adalah `fetch` tahu bagaimana bekerja dengan objek `AborController`, itu terintegrasi dengannya. |
54 | 55 |
|
55 | | -## Using with fetch |
| 56 | +## Menggunakan dengan fetch |
56 | 57 |
|
57 | | -To become able to cancel `fetch`, pass the `signal` property of an `AbortController` as a `fetch` option: |
| 58 | +Untuk bisa membatalkan `fetch`, teruskan properti `signal` dari `AbortController` sebagai opsi `fetch`: |
58 | 59 |
|
59 | 60 | ```js |
60 | 61 | let controller = new AbortController(); |
61 | 62 | fetch(url, { |
62 | | - signal: controller.signal |
| 63 | + signal: controller.signal, |
63 | 64 | }); |
64 | 65 | ``` |
65 | 66 |
|
66 | | -The `fetch` method knows how to work with `AbortController`. It will listen to `abort` events on `signal`. |
| 67 | +Metode `fetch` mengetahui bagaimana cara bekerja dengan `AbortController`. Itu akan mendengarkan (_listen_) _event_ `abort` pada properti `signal`. |
67 | 68 |
|
68 | | -Now, to to abort, call `controller.abort()`: |
| 69 | +Sekarang, untuk membatalkannya, panggil `controller.abort()`: |
69 | 70 |
|
70 | 71 | ```js |
71 | 72 | controller.abort(); |
72 | 73 | ``` |
73 | 74 |
|
74 | | -We're done: `fetch` gets the event from `signal` and aborts the request. |
| 75 | +Kita sudah selesai: `fetch` mendapatkan _event_ dari properti `signal` dan membatalkan _request_. |
75 | 76 |
|
76 | | -When a fetch is aborted, its promise rejects with an error `AbortError`, so we should handle it, e.g. in `try..catch`. |
| 77 | +Ketika `fetch` dibatalkan, maka `promise` akan ditolak dengan galat `AboutError`, jadi kita dapat menanganinya. Misalnya dengan `try ... catch`. |
77 | 78 |
|
78 | | -Here's the full example with `fetch` aborted after 1 second: |
| 79 | +Berikut adalah contoh penuh untuk menggagalkan `fetch` setelah 1 detik: |
79 | 80 |
|
80 | 81 | ```js run async |
81 | | -// abort in 1 second |
| 82 | +// gagalkan setelah satu detik |
82 | 83 | let controller = new AbortController(); |
83 | 84 | setTimeout(() => controller.abort(), 1000); |
84 | 85 |
|
85 | 86 | try { |
86 | 87 | let response = await fetch('/article/fetch-abort/demo/hang', { |
87 | | - signal: controller.signal |
| 88 | + signal: controller.signal, |
88 | 89 | }); |
89 | | -} catch(err) { |
90 | | - if (err.name == 'AbortError') { // handle abort() |
91 | | - alert("Aborted!"); |
| 90 | +} catch (err) { |
| 91 | + if (err.name == 'AbortError') { |
| 92 | + // menangani ketika digagalkan |
| 93 | + alert('Aborted!'); |
92 | 94 | } else { |
93 | 95 | throw err; |
94 | 96 | } |
95 | 97 | } |
96 | 98 | ``` |
97 | 99 |
|
98 | | -## AbortController is scalable |
| 100 | +## AbortController dapat ditingkatkan (_scalable_) |
99 | 101 |
|
100 | | -`AbortController` is scalable, it allows to cancel multiple fetches at once. |
| 102 | +`AbortContoller` bersifat _scalable_, itu memungkinkan untuk membatalkan beberapa `fetch` sekaligus. |
101 | 103 |
|
102 | | -Here's a sketch of code that fetches many `urls` in parallel, and uses a single controller to abort them all: |
| 104 | +Berikut adalah sketsa dari kode yang terdapat proses `fetch` ke banyak `urls` secara paralel, dan menggunakan pengontrol tunggal untuk membatalkan semua proses tersebut: |
103 | 105 |
|
104 | 106 | ```js |
105 | | -let urls = [...]; // a list of urls to fetch in parallel |
| 107 | +let urls = [...]; // daftar dari url yang akan diambil secara paralel |
106 | 108 |
|
107 | 109 | let controller = new AbortController(); |
108 | 110 |
|
109 | | -// an array of fetch promises |
| 111 | +// larik dari 'fetch promise' |
110 | 112 | let fetchJobs = urls.map(url => fetch(url, { |
111 | 113 | signal: controller.signal |
112 | 114 | })); |
113 | 115 |
|
114 | 116 | let results = await Promise.all(fetchJobs); |
115 | 117 |
|
116 | | -// if controller.abort() is called from elsewhere, |
117 | | -// it aborts all fetches |
| 118 | +// jika controller.fetch() dipanggil dari tempat tertentu |
| 119 | +// itu akan menggagalkan semua 'fetch' |
118 | 120 | ``` |
119 | 121 |
|
120 | | -If we have our own asynchronous tasks, different from `fetch`, we can use a single `AbortController` to stop those, together with fetches. |
| 122 | +Jika kita memiliki tugas asingkron kita sendiri yang berbeda dari `fetch`, kita dapat menggunakan `AbortController` tunggal untuk menghentikannya, bersama dengan metode `fetch`. |
121 | 123 |
|
122 | | -We just need to listen to its `abort` event in our tasks: |
| 124 | +Kita hanya perlu untuk `listen` pada _event_ `abort` di tugas kita; |
123 | 125 |
|
124 | 126 | ```js |
125 | 127 | let urls = [...]; |
126 | 128 | let controller = new AbortController(); |
127 | 129 |
|
128 | | -let ourJob = new Promise((resolve, reject) => { // our task |
| 130 | +let ourJob = new Promise((resolve, reject) => { // tugas kita |
129 | 131 | ... |
130 | 132 | controller.signal.addEventListener('abort', reject); |
131 | 133 | }); |
132 | 134 |
|
133 | | -let fetchJobs = urls.map(url => fetch(url, { // fetches |
| 135 | +let fetchJobs = urls.map(url => fetch(url, { // pemanggilan metode fetch |
134 | 136 | signal: controller.signal |
135 | 137 | })); |
136 | 138 |
|
137 | | -// Wait for fetches and our task in parallel |
| 139 | +// Menunggu semua metode fetch dan tugas kita secara paralel |
138 | 140 | let results = await Promise.all([...fetchJobs, ourJob]); |
139 | 141 |
|
140 | | -// if controller.abort() is called from elsewhere, |
141 | | -// it aborts all fetches and ourJob |
| 142 | +// Jika controller.abort() dipanggil dari suatu tempat, |
| 143 | +// itu menggagalkan semua metode fetch dan tugas kita |
142 | 144 | ``` |
143 | 145 |
|
144 | | -## Summary |
| 146 | +## Kesimpulan |
145 | 147 |
|
146 | | -- `AbortController` is a simple object that generates `abort` event on it's `signal` property when `abort()` method is called (and also sets `signal.aborted` to `true`). |
147 | | -- `fetch` integrates with it: we pass `signal` property as the option, and then `fetch` listens to it, so it becomes possible to abort the `fetch`. |
148 | | -- We can use `AbortController` in our code. The "call `abort()`" -> "listen to `abort` event" interaction is simple and universal. We can use it even without `fetch`. |
| 148 | +- `AbortController` adalah sebuah objek sederhana yang menghasilkan _event_ `abort` pada properti `signal` ketika metode `abort()` dipanggil (dan juga menyetel `signal.aborted` menjadi `true`). |
| 149 | +- `fetch` terintegrasi dengannya: kita meneruskan properti `signal` sebagai opsi, dan kemudian `fetch` mendengarkan event yang dihasilkan `AbortController`. Jadi itu menjadi mungkin ketika ingin menggagalkan proses `fetch`. |
| 150 | +- Kita dapat menggunakan `AbortConntroller` pada kode kita. Interaksi "pemanggilan `abort()`" -> "Mendengarkan (_listen_) _event_ `abort`" sederhana dan universal. Kita dapat menggunakannya walaupun tanpa `fetch`. |
0 commit comments