diff --git a/1-js/12-generators-iterators/2-async-iterators-generators/article.md b/1-js/12-generators-iterators/2-async-iterators-generators/article.md index 704ba0672..057972541 100644 --- a/1-js/12-generators-iterators/2-async-iterators-generators/article.md +++ b/1-js/12-generators-iterators/2-async-iterators-generators/article.md @@ -1,33 +1,33 @@ +# Iterasi dan generator asinkron -# Async iteration and generators +Iterasi asinkron memungkinkan kita melakukan iterasi atas data yang datang secara asinkron, sesuai permintaan. Seperti, misalnya, ketika kita mengunduh sesuatu yang sepotong demi sepotong melalui jaringan. Dan generator asinkron membuatnya lebih nyaman. -Asynchronous iteration allow us to iterate over data that comes asynchronously, on-demand. Like, for instance, when we download something chunk-by-chunk over a network. And asynchronous generators make it even more convenient. +Mari kita lihat contoh sederhana terlebih dahulu, untuk memahami sintaksnya, lalu meninjau kasus penggunaan kehidupan nyata. -Let's see a simple example first, to grasp the syntax, and then review a real-life use case. +## Ingat _iterable_ -## Recall iterables +Mari kita ingat topik tentang _iterable_. -Let's recall the topic about iterables. +Idenya adalah kita memiliki objek, seperti `range` di sini: -The idea is that we have an object, such as `range` here: ```js let range = { from: 1, - to: 5 + to: 5, }; ``` -...And we'd like to use `for..of` loop on it, such as `for(value of range)`, to get values from `1` to `5`. +...Dan kita ingin menggunakan perulangan `for..of` di atasnya, seperti `for(value of range)`, untuk mendapatkan nilai dari `1` hingga `5`. -In other words, we want to add an *iteration ability* to the object. +Dengan kata lain, kita ingin menambahkan kemampuan iterasi ke objek. -That can be implemented using a special method with the name `Symbol.iterator`: +Itu bisa diimplementasikan menggunakan metode khusus dengan nama `Symbol.iterator`: -- This method is called in by the `for..of` construct when the loop is started, and it should return an object with the `next` method. -- For each iteration, the `next()` method is invoked for the next value. -- The `next()` should return a value in the form `{done: true/false, value:}`, where `done:true` means the end of the loop. +- Metode ini dipanggil oleh konstruksi `for..of` ketika perulangan dimulai, dan harus mengembalikan objek dengan metode `next`. +- Untuk setiap iterasi, metode `next()` dipanggil untuk nilai berikutnya. +- `next()` harus mengembalikan nilai dalam bentuk `{done: true/false, value:}`, di mana `done:true` berarti akhir dari perulangan. -Here's an implementation for the iterable `range`: +Berikut implementasi untuk `range` _iterable_: ```js run let range = { @@ -35,14 +35,14 @@ let range = { to: 5, *!* - [Symbol.iterator]() { // called once, in the beginning of for..of + [Symbol.iterator]() { // dipanggil sekali, di awal for..of */!* return { current: this.from, last: this.to, *!* - next() { // called every iteration, to get the next value + next() { // memanggil setiap iterasi, untuk mendapatkan nilai berikutnya */!* if (this.current <= this.last) { return { done: false, value: this.current++ }; @@ -55,29 +55,29 @@ let range = { }; for(let value of range) { - alert(value); // 1 then 2, then 3, then 4, then 5 + alert(value); // 1 lalu 2, lalu 3, lalu 4, lalu 5 } ``` -If anything is unclear, please visit the chapter [](info:iterable), it gives all the details about regular iterables. +Jika ada yang tidak jelas, silakan kunjungi bab [](info:iterable), ini memberikan semua detail tentang iterable biasa. -## Async iterables +## _Iterable_ asinkron -Asynchronous iteration is needed when values come asynchronously: after `setTimeout` or another kind of delay. +Iterasi asinkron diperlukan jika nilai muncul secara asinkron: setelah `setTimeout` atau jenis penundaan lainnya. -The most common case is that the object needs to make a network request to deliver the next value, we'll see a real-life example of it a bit later. +Kasus yang paling umum adalah objek perlu membuat permintaan jaringan untuk memberikan nilai berikutnya, kita akan melihat contoh kehidupan nyata nanti. -To make an object iterable asynchronously: +Untuk membuat sebuah objek dapat diulang secara asinkron: -1. Use `Symbol.asyncIterator` instead of `Symbol.iterator`. -2. The `next()` method should return a promise (to be fulfilled with the next value). - - The `async` keyword handles it, we can simply make `async next()`. -3. To iterate over such an object, we should use a `for await (let item of iterable)` loop. - - Note the `await` word. +1. Gunakan `Symbol.asyncIterator` sebagai ganti `Symbol.iterator`. +2. Metode `next()` harus mengembalikan sebuah _promise_ (untuk dipenuhi dengan nilai berikutnya). + - Kata kunci `async` menanganinya, kita cukup membuat `async next() `. +3. Untuk melakukan iterasi pada objek seperti itu, kita harus menggunakan perulangan `for await (let item of iterable)`. + - Perhatikan kata `await`. -As a starting example, let's make an iterable `range` object, similar like the one before, but now it will return values asynchronously, one per second. +Sebagai contoh awal, mari kita buat objek `range` yang dapat diulang, serupa seperti sebelumnya, tetapi sekarang akan mengembalikan nilai secara asinkron, satu per detik. -All we need to do is to perform a few replacements in the code above: +Yang perlu kita lakukan adalah melakukan beberapa penggantian pada kode di atas: ```js run let range = { @@ -96,7 +96,7 @@ let range = { */!* *!* - // note: we can use "await" inside the async next: + // catatan: kita bisa menggunakan "await" di dalam async next: await new Promise(resolve => setTimeout(resolve, 1000)); // (3) */!* @@ -121,43 +121,45 @@ let range = { })() ``` -As we can see, the structure is similar to regular iterators: +Seperti yang bisa kita lihat, strukturnya mirip dengan iterator biasa: + +1. Untuk membuat sebuah objek asinkron _iterable_, itu harus memiliki metode `Symbol.asyncIterator` `(1)`. +2. Metode ini harus mengembalikan objek dengan metode `next()` mengembalikan _promise_ `(2)`. +3. Metode `next()` tidak harus menjadi `async`, ini mungkin metode biasa yang mengembalikan sebuah _promise_, tetapi `async` memungkinkan kita untuk menggunakan `await`, jadi itu mudah. Disini kita hanya menunda sebentar `(3)`. +4. Untuk iterasi, kita menggunakan `for await(let value of range)` `(4)`, yaitu menambahkan "await" setelah "for". Ini memanggil `range[Symbol.asyncIterator]()` sekali, dan kemudian `next()` untuk nilai. -1. To make an object asynchronously iterable, it must have a method `Symbol.asyncIterator` `(1)`. -2. This method must return the object with `next()` method returning a promise `(2)`. -3. The `next()` method doesn't have to be `async`, it may be a regular method returning a promise, but `async` allows us to use `await`, so that's convenient. Here we just delay for a second `(3)`. -4. To iterate, we use `for await(let value of range)` `(4)`, namely add "await" after "for". It calls `range[Symbol.asyncIterator]()` once, and then its `next()` for values. +Berikut tabel kecil dengan perbedaannya: -Here's a small table with the differences: +| | Iterator | Iterator Asinkron | +| --------------------------------------- | ----------------- | ---------------------- | +| Metode objek untuk menyediakan iterator | `Symbol.iterator` | `Symbol.asyncIterator` | +| Nilai kembali `next()` adalah | nilai apapun | `Promise` | +| Untuk mengulang, gunakan | `for..of` | `for await..of` | -| | Iterators | Async iterators | -|-------|-----------|-----------------| -| Object method to provide iterator | `Symbol.iterator` | `Symbol.asyncIterator` | -| `next()` return value is | any value | `Promise` | -| to loop, use | `for..of` | `for await..of` | +````warn header="Sintaks _spread_ `...` tidak bekerja secara asinkron" +Fitur yang membutuhkan iterator sinkron dan reguler, tidak berfungsi dengan yang asinkron. -````warn header="The spread syntax `...` doesn't work asynchronously" -Features that require regular, synchronous iterators, don't work with asynchronous ones. +Misalnya, sintaks _spread_ tidak akan berfungsi: -For instance, a spread syntax won't work: ```js -alert( [...range] ); // Error, no Symbol.iterator +alert([...range]); // Error, no Symbol.iterator (tidak ada Symbol.iterator) ``` -That's natural, as it expects to find `Symbol.iterator`, not `Symbol.asyncIterator`. +Itu wajar, karena mengharapkan untuk menemukan `Symbol.iterator`, bukan `Symbol.asyncIterator`. -It's also the case for `for..of`: the syntax without `await` needs `Symbol.iterator`. -```` +Ini juga kasus untuk `for..of`: sintaks tanpa `await` membutuhkan` Symbol.iterator`. -## Recall generators +````` -Now let's recall generators, as they allow to make iteration code much shorter. Most of the time, when we'd like to make an iterable, we'll use generators. +## Ingat generator -For sheer simplicity, omitting some important stuff, they are "functions that generate (yield) values". They are explained in detail in the chapter [](info:generators). +Sekarang mari kita ingat generator, karena memungkinkan untuk membuat kode iterasi jauh lebih pendek. Seringkali, ketika kita ingin membuat _iterable_, kita akan menggunakan generator. -Generators are labelled with `function*` (note the start) and use `yield` to generate a value, then we can use `for..of` to loop over them. +Untuk kesederhanaan semata, menghilangkan beberapa hal penting, mereka adalah "fungsi yang menghasilkan nilai". Mereka dijelaskan secara rinci di bab [] (info:generators). -This example generates a sequence of values from `start` to `end`: +Generator diberi label dengan `function*` (catat permulaannya) dan gunakan `yield` untuk menghasilkan nilai, kemudian kita dapat menggunakan `for..of` untuk mengulanginya. + +Contoh ini menghasilkan urutan nilai dari `start` hingga `end`: ```js run function* generateSequence(start, end) { @@ -167,11 +169,11 @@ function* generateSequence(start, end) { } for(let value of generateSequence(1, 5)) { - alert(value); // 1, then 2, then 3, then 4, then 5 + alert(value); // 1, lalu 2, lalu 3, lalu 4, lalu 5 } ``` -As we already know, to make an object iterable, we should add `Symbol.iterator` to it. +Seperti yang telah kita ketahui, untuk membuat sebuah objek menjadi _iterable_, kita harus menambahkan `Symbol.iterator` padanya. ```js let range = { @@ -179,20 +181,20 @@ let range = { to: 5, *!* [Symbol.iterator]() { - return + return } */!* } ``` -A common practice for `Symbol.iterator` is to return a generator, it makes the code shorter, as you can see: +Praktik umum untuk `Symbol.iterator` adalah mengembalikan generator, ini membuat kode lebih pendek, seperti yang kamu lihat: ```js run let range = { from: 1, to: 5, - *[Symbol.iterator]() { // a shorthand for [Symbol.iterator]: function*() + *[Symbol.iterator]() { // singkatan untuk [Symbol.iterator]: function*() for(let value = this.from; value <= this.to; value++) { yield value; } @@ -200,25 +202,25 @@ let range = { }; for(let value of range) { - alert(value); // 1, then 2, then 3, then 4, then 5 + alert(value); // 1, lalu 2, lalu 3, lalu 4, lalu 5 } ``` -Please see the chapter [](info:generators) if you'd like more details. +Silakan lihat bab [](info:generators) jika kamu ingin lebih jelasnya. -In regular generators we can't use `await`. All values must come synchronously, as required by the `for..of` construct. +Di generator biasa kita tidak bisa menggunakan `await`. Semua nilai harus datang secara sinkron, seperti yang diharuskan oleh konstruksi `for..of`. -What if we'd like to generate values asynchronously? From network requests, for instance. +Bagaimana jika kita ingin menghasilkan nilai secara asinkron? Dari permintaan jaringan, misalnya. -Let's switch to asynchronous generators to make it possible. +Mari beralih ke generator asinkron untuk memungkinkannya. -## Async generators (finally) +## Generator asinkron (akhirnya) -For most practical applications, when we'd like to make an object that asynchronously generates a sequence of values, we can use an asynchronous generator. +Untuk sebagian besar aplikasi praktis, ketika kita ingin membuat objek yang menghasilkan urutan nilai secara asinkron, kita dapat menggunakan generator asinkron. -The syntax is simple: prepend `function*` with `async`. That makes the generator asynchronous. +Sintaksnya sederhana: tambahkan `function*` dengan `async`. Itu membuat generator asinkron. -And then use `for await (...)` to iterate over it, like this: +Dan kemudian gunakan `for await (...)` untuk mengulanginya, seperti ini: ```js run *!*async*/!* function* generateSequence(start, end) { @@ -239,47 +241,47 @@ And then use `for await (...)` to iterate over it, like this: let generator = generateSequence(1, 5); for *!*await*/!* (let value of generator) { - alert(value); // 1, then 2, then 3, then 4, then 5 (with delay between) + alert(value); // 1, lalu 2, lalu 3, lalu 4, lalu 5 (dengan penundaan antaranya) } })(); ``` -As the generator is asynchronous, we can use `await` inside it, rely on promises, perform network requests and so on. +Karena generatornya asinkron, kita bisa menggunakan `await` di dalamnya, mengandalkan _promise_, melakukan permintaan jaringan, dan sebagainya. -````smart header="Under-the-hood difference" -Technically, if you're an advanced reader who remembers the details about generators, there's an internal difference. +````smart header="Perbedaan didalamnya" +Secara teknis, jika kamu adalah pembaca tingkat lanjut yang mengingat detail tentang generator, ada perbedaan internal. -For async generators, the `generator.next()` method is asynchronous, it returns promises. +Untuk generator asinkron, metode `generator.next()` adalah asinkron, yang mengembalikan _promise_. -In a regular generator we'd use `result = generator.next()` to get values. In an async generator, we should add `await`, like this: +Dalam generator biasa kita akan menggunakan `result = generator.next()` untuk mendapatkan nilai. Dalam generator asinkron, kita harus menambahkan `await`, seperti ini: ```js result = await generator.next(); // result = {value: ..., done: true/false} ``` -That's why async generators work with `for await...of`. -```` +Itulah mengapa generator asinkron bekerja dengan `for await...of`. +````` -### Async iterable range +### Rentang _iterable_ asinkron -Regular generators can be used as `Symbol.iterator` to make the iteration code shorter. +Generator biasa dapat digunakan sebagai `Symbol.iterator` untuk mempersingkat kode iterasi. -Similar to that, async generators can be used as `Symbol.asyncIterator` to implement the asynchronous iteration. +Serupa dengan itu, generator asinkron dapat digunakan sebagai `Symbol.asyncIterator` untuk mengimplementasikan iterasi asinkron. -For instance, we can make the `range` object generate values asynchronously, once per second, by replacing synchronous `Symbol.iterator` with asynchronous `Symbol.asyncIterator`: +Misalnya, kita dapat membuat objek `range` menghasilkan nilai secara asinkron, sekali per detik, dengan mengganti `Symbol.iterator` sinkron dengan `Symbol.asyncIterator` asinkron: ```js run let range = { from: 1, to: 5, - // this line is same as [Symbol.asyncIterator]: async function*() { + // baris ini sama dengan [Symbol.asyncIterator]: async function*() { *!* async *[Symbol.asyncIterator]() { */!* for(let value = this.from; value <= this.to; value++) { - // make a pause between values, wait for something + // buat jeda di antara value, tunggu sesuatu await new Promise(resolve => setTimeout(resolve, 1000)); yield value; @@ -290,126 +292,129 @@ let range = { (async () => { for *!*await*/!* (let value of range) { - alert(value); // 1, then 2, then 3, then 4, then 5 + alert(value); // 1, lalu 2, lalu 3, lalu 4, lalu 5 } })(); ``` -Now values come with a delay of 1 second between them. +Sekarang _value_ datang dengan jeda 1 detik di antara mereka. ```smart -Technically, we can add both `Symbol.iterator` and `Symbol.asyncIterator` to the object, so it's both synchronously (`for..of`) and asynchronously (`for await..of`) iterable. +Secara teknis, kita bisa menambahkan `Symbol.iterator` dan `Symbol.asyncIterator` ke objek, jadi keduanya secara sinkron (`for..of`) dan asinkron (`for await..of`) _iterable_. -In practice though, that would be an weird thing to do. +Namun dalam praktiknya, itu akan menjadi hal yang aneh untuk dilakukan. ``` -## Real-life example: paginated data +## Contoh kehidupan nyata: _paginated_ data -So far we've seen basic examples, to gain understanding. Now let's review a real-life use case. +Sejauh ini kita telah melihat contoh-contoh dasar, untuk mendapatkan pemahaman. Sekarang mari kita tinjau kasus penggunaan kehidupan nyata. -There are many online services that deliver paginated data. For instance, when we need a list of users, a request returns a pre-defined count (e.g. 100 users) - "one page", and provides a URL to the next page. +Ada banyak layanan daring yang memberikan _paginated_ data. Misalnya, saat kita membutuhkan daftar pengguna, permintaan mengembalikan jumlah yang telah ditentukan sebelumnya (misalnya 100 pengguna) - "satu halaman", dan memberikan URL ke halaman berikutnya. -This pattern is very common. It's not about users, but just about anything. +Pola ini sangat umum. Ini bukan tentang pengguna, tetapi tentang apa saja. -For instance, GitHub allows us to retrieve commits in the same, paginated fashion: +Misalnya, GitHub memungkinkan kita untuk mengambil _commits_ dengan cara yang sama, _paginated_: -- We should make a request to `fetch` in the form `https://api.github.com/repos//commits`. -- It responds with a JSON of 30 commits, and also provides a link to the next page in the `Link` header. -- Then we can use that link for the next request, to get more commits, and so on. +- Kita harus membuat permintaan untuk `fetch` dalam formulir `https://api.github.com/repos//commits`. +- Ini merespons dengan JSON 30 _commits_, dan juga menyediakan tautan ke halaman berikutnya di tajuk `Link`. +- Lalu kita bisa menggunakan tautan itu untuk permintaan berikutnya, untuk mendapatkan lebih banyak _commits_, dan seterusnya. -For our code, we'd like to have a simpler way to get commits. +Untuk kode kita, kita ingin memiliki cara yang lebih sederhana untuk mendapatkan _commits_. -Let's make a function `fetchCommits(repo)` that gets commits for us, making requests whenever needed. And let it care about all pagination stuff. For us it'll be a simple async iteration `for await..of`. +Mari buat fungsi `fetchCommits(repo)` yang mendapatkan _commits_ untuk kita, membuat permintaan kapan pun diperlukan. Dan biarkan peduli tentang semua hal penomoran halaman. Bagi kita ini akan menjadi iterasi asinkron sederhana `for await..of`. -So the usage will be like this: +Jadi penggunaannya akan seperti ini: ```js -for await (let commit of fetchCommits("username/repository")) { - // process commit +for await (let commit of fetchCommits('username/repository')) { + // proses commit } ``` -Here's such function, implemented as async generator: +Berikut fungsi tersebut, diimplementasikan sebagai generator asinkron: ```js async function* fetchCommits(repo) { let url = `https://api.github.com/repos/${repo}/commits`; while (url) { - const response = await fetch(url, { // (1) - headers: {'User-Agent': 'Our script'}, // github needs any user-agent header + const response = await fetch(url, { + // (1) + headers: { 'User-Agent': 'Our script' }, // github membutuhkan header user-agent }); - const body = await response.json(); // (2) response is JSON (array of commits) + const body = await response.json(); // (2) respon adalah JSON (senarai commits) - // (3) the URL of the next page is in the headers, extract it + // (3) URL halaman berikutnya ada di header, ekstrak itu let nextPage = response.headers.get('Link').match(/<(.*?)>; rel="next"/); nextPage = nextPage?.[1]; url = nextPage; - for(let commit of body) { // (4) yield commits one by one, until the page ends + for (let commit of body) { + // (4) menghasilkan commit satu per satu, sampai halaman berakhir yield commit; } } } ``` -More explanations about how it works: +Penjelasan lebih lanjut tentang cara kerjanya: + +1. Kita menggunakan metode peramban [fetch](info:fetch) untuk mengunduh _commits_. -1. We use the browser [fetch](info:fetch) method to download the commits. + - URL awalnya adalah `https://api.github.com/repos//commits`, dan halaman berikutnya akan berada di `Link` header tanggapan. + - Metode `fetch` memungkinkan kita untuk memberikan otorisasi dan tajuk lainnya jika diperlukan -- di sini GitHub memerlukan `User-Agent`. - - The initial URL is `https://api.github.com/repos//commits`, and the next page will be in the `Link` header of the response. - - The `fetch` method allows us to supply authorization and other headers if needed -- here GitHub requires `User-Agent`. -2. The commits are returned in JSON format. -3. We should get the next page URL from the `Link` header of the response. It has a special format, so we use a regular expression for that. - - The next page URL may look like `https://api.github.com/repositories/93253246/commits?page=2`. It's generated by GitHub itself. -4. Then we yield the received commits one by one, and when they finish, the next `while(url)` iteration will trigger, making one more request. +2. _commits_ dikembalikan dalam format JSON. +3. Kita harus mendapatkan URL halaman berikutnya dari tajuk `Link` dari respon. Ini memiliki format khusus, jadi kita menggunakan ekspresi reguler untuk itu. + - URL halaman berikutnya mungkin terlihat seperti ini `https://api.github.com/repositories/93253246/commits?page=2`. Ini dihasilkan oleh GitHub itu sendiri. +4. Kemudian kita menghasilkan _commits_ yang diterima satu per satu, dan ketika mereka selesai, iterasi `while(url)` berikutnya akan terpicu, membuat satu permintaan lagi. -An example of use (shows commit authors in console): +Contoh penggunaan (menunjukkan penulis _commit_ di konsol): ```js run (async () => { - let count = 0; - for await (const commit of fetchCommits('javascript-tutorial/en.javascript.info')) { - + for await (const commit of fetchCommits( + 'javascript-tutorial/en.javascript.info' + )) { console.log(commit.author.login); - if (++count == 100) { // let's stop at 100 commits + if (++count == 100) { + // mari berhenti di 100 commits break; } } - })(); ``` -That's just what we wanted. +Itulah yang kita inginkan. -The internal mechanics of paginated requests is invisible from the outside. For us it's just an async generator that returns commits. +Mekanisme internal permintaan _paginated_ tidak terlihat dari luar. Bagi kita, ini hanyalah generator asinkron yang mengembalikan _commits_. -## Summary +## Ringkasan -Regular iterators and generators work fine with the data that doesn't take time to generate. +Iterator dan generator reguler berfungsi dengan baik dengan data yang tidak membutuhkan waktu untuk dibuat. -When we expect the data to come asynchronously, with delays, their async counterparts can be used, and `for await..of` instead of `for..of`. +Saat kita mengharapkan data datang secara asinkron, dengan penundaan, pasangan asinkronnya dapat digunakan, dan `for await..of` daripada `for..of`. -Syntax differences between async and regular iterators: +Perbedaan sintaks antara asinkron dan iterator biasa: -| | Iterable | Async Iterable | -|-------|-----------|-----------------| -| Method to provide iterator | `Symbol.iterator` | `Symbol.asyncIterator` | -| `next()` return value is | `{value:…, done: true/false}` | `Promise` that resolves to `{value:…, done: true/false}` | +| | _Iterable_ | Asinkron _Iterable_ | +| --------------------------------- | ----------------------------- | ------------------------------------------------------------- | +| Metode untuk menyediakan iterator | `Symbol.iterator` | `Symbol.asyncIterator` | +| Nilai kembali `next()` adalah | `{value:…, done: true/false}` | `Promise` yang memutuskan untuk `{value:…, done: true/false}` | -Syntax differences between async and regular generators: +Perbedaan sintaks antara generator asinkron dan biasa: -| | Generators | Async generators | -|-------|-----------|-----------------| -| Declaration | `function*` | `async function*` | -| `next()` return value is | `{value:…, done: true/false}` | `Promise` that resolves to `{value:…, done: true/false}` | +| | Generator | Generator asinkron | +| ----------------------------- | ----------------------------- | ------------------------------------------------------------- | +| Deklarasi | `function*` | `async function*` | +| Nilai kembali `next()` adalah | `{value:…, done: true/false}` | `Promise` yang memutuskan untuk `{value:…, done: true/false}` | -In web-development we often meet streams of data, when it flows chunk-by-chunk. For instance, downloading or uploading a big file. +Dalam pengembangan web, kita sering menemui aliran data, ketika mengalir potongan demi potongan. Misalnya, mengunduh atau mengunggah file besar. -We can use async generators to process such data. It's also noteworthy that in some environments, like in browsers, there's also another API called Streams, that provides special interfaces to work with such streams, to transform the data and to pass it from one stream to another (e.g. download from one place and immediately send elsewhere). +Kita dapat menggunakan generator asinkron untuk memproses data tersebut. Perlu juga dicatat bahwa di beberapa lingkungan, seperti di peramban, ada juga Antarmuka Pemrograman Aplikasi (APA) lain yang disebut _Streams_, yang menyediakan antarmuka khusus untuk bekerja dengan aliran semacam itu, untuk mengubah data dan meneruskannya dari satu aliran ke aliran lain (misalnya mengunduh dari satu tempat dan segera kirim ke tempat lain). diff --git a/1-js/12-generators-iterators/2-async-iterators-generators/head.html b/1-js/12-generators-iterators/2-async-iterators-generators/head.html index 03f21e2bd..931181dba 100644 --- a/1-js/12-generators-iterators/2-async-iterators-generators/head.html +++ b/1-js/12-generators-iterators/2-async-iterators-generators/head.html @@ -4,19 +4,19 @@ while (url) { const response = await fetch(url, { - headers: {'User-Agent': 'Our script'}, // github requires user-agent header + headers: { 'User-Agent': 'Our script' }, // github membutuhkan header user-agent }); - const body = await response.json(); // parses response as JSON (array of commits) + const body = await response.json(); // mem-parsing respons sebagai JSON (senarai commits) - // the URL of the next page is in the headers, extract it + // URL halaman berikutnya ada di header, ekstrak itu let nextPage = response.headers.get('Link').match(/<(.*?)>; rel="next"/); nextPage = nextPage?.[1]; url = nextPage; - // yield commits one by one, when they finish - fetch a new page url - for(let commit of body) { + // menghasilkan commit satu per satu, setelah selesai - ambil url halaman baru + for (let commit of body) { yield commit; } } diff --git a/1-js/12-generators-iterators/index.md b/1-js/12-generators-iterators/index.md index ccc909d1a..d10b4ef4e 100644 --- a/1-js/12-generators-iterators/index.md +++ b/1-js/12-generators-iterators/index.md @@ -1,2 +1 @@ - -# Generators, advanced iteration +# Generator, iterasi lanjutan pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy