This is the 9th day of my participation in the August Wen Challenge.More challenges in August

preface

ES6’s Iterator objects provide a uniform traversal for all data structures with Iterator interfaces deployed, but this traversal is only suitable for synchronous data sources. For pages with lots of interaction, there are often many asynchronous data sources, such as network requests, file I/O, or stream operations, and so on. However, there is no quick and uniform way to traverse.

One of ES2018’s new features is Asynchronous iteration, a generic traversal interface designed specifically for Asynchronous data sources.

for-await-of

For parallel requests, we can use promise. all for unified processing, but for the ordered and partialized data source like stream, we can’t handle it all at once through callback, we must use polling, and we will handle it once the data block arrives. If we do not use asynchronous iterators, how to handle it? Here is an example from juejin challenge (Juejin. Cn) that gives you a thorough and in-depth understanding of the Stream API in JS:

const readableStream = newReadableStream({... }, {... });// Create a reader
const reader = readableStream.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) {
    console.log('Data read completed');
    break;
  }
  console.log('The original value of the data block is :', value);
}
Copy the code

The example uses an infinite loop to poll the incoming stream, based on the event loop, so this infinite loop does not block the main thread. This is not an elegant way to read asynchronous data sources, so let’s use asynchronous iterators instead.

const readableStream = newReadableStream({... }, {... });// Create a reader
const reader = readableStream.getReader();
for await(const value of reader.read()){
  console.log('The original value of the data block is :', value);
}
Copy the code

Readable streams have a built-in asynchronous iterator interface, so we use for-await-of to iterate over each chunk of data. We don’t care when the stream is finished, just focus on processing the data itself, with the same precision and elegance as synchronous data.

Deploy the iterator interface

If an object can be called for.. Asynchronous iterators are deployed in the same way as synchronous iterators. It also requires [symbol.asynciterator]. In addition, the next iterator returns a Promise:

Synchronous iterator

 const iterator = {
    [Symbol.iterator]: () = > {
     const items = ['J'.'a'.'y'.'l'.'e'.'n'.'L'];
     return {
         next: () = >{
             done: items.length === 0.value: items.shift()
       }
     }
   }
 }
Copy the code

Asynchronous iterator

 const asyncIterator = {
    [Symbol.asyncIterator]: () = > {
     const items = ['J'.'a'.'y'.'l'.'e'.'n'.'L'];
     return {
         next: () = > Promise.resolve({
             done: items.length === 0.value: items.shift()
       })
     }
   }
 }
Copy the code

The difference is clear. Here’s another example to deepen your understanding, copy to the console and run:

let asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 1.next() {
        if (this.i <= 10) {
          return new Promise((resolve) = > {
            setTimeout(() = > resolve({
              value: this.i++,
              done: false
            }), 1000);
          });
        }
        return Promise.resolve({
          done: true}); }}; }}; (async() = > {for await (let item of asyncIterable) {
    const val = await item;
    console.log(val);
  }
})();
Copy the code

The above example prints a number every second.

Matters needing attention

Extended operators… The iterator interface that iterates through the object is called internally, but it can only use synchronous iterators, not with asynchronous iterators,

conclusion

Asynchronous iterators are especially suitable for processing data streams, and are widely used in Node. When combined with the generator, it is an asynchronous generator. It can be used to realize asynchronous I/O flow control, large file uploading, streaming media processing, etc.

Syntax Differences between asynchronous iterators and synchronous iterators:

Synchronization of the Iterator Asynchronous Iterator
Iterator interface [Symbol.iterator] [Symbol.asyncIterator]
next()The value returned {value:... , done: true/false} Resolve to{value:... , done: true/false}Promise