4

What is good reason for using ES iterators? I know what is using on generator functions(function with *) for async actions. Which are other use cases for pure iterators?

Give me please few examples from real life, it doesn't matter from node.js or browser usage.

slava_slava
  • 636
  • 1
  • 10
  • 23
  • 4
    They aren't unique to JavaScript. Are you aware of how they're used in other languages? – 4castle Jul 16 '17 at 18:10
  • I'm not sure what kind of examples you're looking for other than "iterating things". If you've ever used ES5 `.forEach` or used a loop, you know the big usecase. Clarifications would help a lot. – loganfsmyth Jul 16 '17 at 18:47
  • Does [What can we do with ES6 Generator that we cannot with for loop?](https://stackoverflow.com/q/23613612/1048572) answer your question? – Bergi Jul 16 '17 at 22:45

2 Answers2

13

Two main reasons:

  1. Language features such as for/of, spread operator, destructing assignment, etc... can be built that work on any object that supports a standard iterator interface.

  2. Programmers using a collection can either use an iterator directly or use it indirectly through the language features that depend upon it and they can interface generically with a collection in many ways without having to know what type of collection it is.

As an example of a language feature in ES6, that uses the iterator standard in the language is that you can have a language construct such as:

for (x of someObj) { ... }

And the for/of logic only uses the iterator interface on someObj. It doesn't have to know anything specific about all the types of objects it can iterate. So, because of that, you can use for/of with ANY kind of object that supports a standard iterator. For example, you can use it with an array, a map, a set, or any custom object you create that supports the iterator interface.

The iterator implementation on a given object defines what elements will be iterable and what order they will be presented in.

Frankly, I find it much more common to use language features that rely on the iterator such as for/of than to actually use an iterator directly so that I can use a collection in a standard way without having to know what type of collection it is.

In my own coding, I've found it very convenient to be able to iterate an object without knowing what kind of object it is. That allows me to design an interface that can be passed either a Set or an Array or sometimes even a Map and as long as all I want to do is to iterate the items in the collection, I don't have to care which it is or code any differently. If the caller happens to have a Set handy, they don't have to convert it to an Array just to call the API - they can just pass the Set. And, the code in the API doesn't have to examine the type it was passed to adapt its behavior.

Iterators are also lazy evaluated. So, there's no need to build a temporary array of the entire collection before you start iterating. This can make iterating a lot more efficient, particular if the collection is large and/or the iteration doesn't go all the way through the collection.

Iterators can be infinite. For example, you could have a Fibonacci iterator that represents an infinite sequence.


Other ES6 features beyond for/of that make use of iterators are:

spread syntax
yield*
destructuring assignment
Array.from()

These features can be used with any object that supports a standard iterator.


See these articles for more detail:

Iterables and iterators in ECMAScript 6

ES6 Iterators and Generators in Practice

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
jfriend00
  • 683,504
  • 96
  • 985
  • 979
0
export const execInBatch = async <T>(
  items: T[],
  batchSize: number,
  callback: (item: T[]) => Promise<void>
) => {
  for (const batch of asChunks(items, batchSize)) {
    await callback(batch);
    await new Promise((resolve) => setTimeout(resolve, 1000));
  }
  return true;
};

export function* asChunks<T>(arr: T[], chunkSize: number) {
  let chunk = [];
  for (const item of arr) {
    chunk.push(item);
    if (chunk.length === chunkSize) {
      yield chunk;
      chunk = [];
    }
  }
  if (chunk.length > 0) {
    yield chunk;
  }
}

(async () => {
  const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  const fn = async (item: number[]) => {
    console.log(item);
    return;
  };
  const data = await execInBatch(items, 2, fn);
  console.log(data);
})();

I have created this function for batch processing task.

  • It's important to not just post code, but to also include a description of what the code does and why you are suggesting it. This helps others understand the context and purpose of the code, and makes it more useful for others who may be reading the question or answer. @Amit Gujar . – DSDmark Dec 29 '22 at 17:45