项目作者: tzachi81
项目描述 :
generators and Iterators in JS
高级语言: JavaScript
项目地址: git://github.com/tzachi81/generators.git
Generators and Iterators in JavaScript
Main points covered in this document
- iterable data types and objects and the iterator protocol
- generator functions and generator object
- generator functions with promises and their late ES8 edtion: async/await.
1. What are iterators?
“iterator is an object which defines a sequence and potentially a return value upon its termination.” (MDN web docs)
Iterable data types and objects
- for..in loop is for enumerable properties (including Object data type) - they return their object keys.
- for..of loop is a method, introduced in ES2015, for iterating over “iterable collections” - they return their object values.
- These are the objects/data-types that have a [Symbol.iterator] function built-in: Array, TypedArray, String, Map, Set.
- for..of loop won’t work with Objects because they are not “iterable”, hence, don’t have the [Symbol.iterator] property by default.
Iterator protocol
An object is an iterator when it implements a next() method:
- next() - returns an object with at least two properties:
- done(bool) - indicates if passed all iterables
- value(any) - returns the current iterable value, undefined for the value of {done: true}.
```js
{value: “someValue”, done: false} // Example for iterator’s return object while in sequence.
{value: undefined, done: true} // Example for iterator’s return object when the sequence is done no more values to yield).
Reference:
2. Generator object and generator functions
- Generator functions are iterator protocol functions that can break the ‘Run-to-completion’ paradigm.
- Calling a generator function does not execute its body immediately, but retuns a Generator object instead.
To execute its body, you have to call the .next() method by its object reference, like so: //gen(), A.K.A the generator function, will return a generator object rather than executing the function's body:
let iterator = gen();
// calling the .next() method will start the generator function's body execution until it will hit the next yield expression.
iterator.next();
- Generator functions can get and pass values with a two-way communication using yield and next().
“The yield keyword is used to pause and resume a generator function *()”. (from: MDN web docs) - The yield* expression is used to delegate to another generator or iterable object.
- A return statement in the function generator will make it finish (done: true).
- A throw exception in the function generator will make it finish (done: true).
Question: Is a generator object an iterator or an iterable?
Answer: An generator object is both iterator and iterable
References:
3. Async/Await vs. Generators with Promises
“Without generators, async functions are very difficult to handle.”
ES6 introduced us generators and promises, and ES8 introduced us a more elegant way to use it with async/await.
Why do we need to understand promises and generators?
- Supporting older platforms.
- Running on older browser versions or older Node.js versions.
- Debugging potentially backwards compatibility compilers (like ‘babel’) issues with async functions.
browsers also implement async functions in a similar way:
- they transform the async code to use generators and promises, quite similar to Babel.
The early use of async/await in ES6 was done by using Generator functions that yielded promises.
The ES6 way to use async functions was by combining genrator functions with promises:
const gen = function* generator() {
const a = yield Promise.resolve(1);
const b = yield Promise.resolve(2);
return a + b;
};
const iterator = gen();
console.log(iterator.next()); // { value: Promise(1), done: false }
console.log(iterator.next()) // { value: Promise(2), done: false }
console.log(iterator.next()) // { value: NaN, done: true }
In ES8 it can be translated to a more elegant code with async/await
const promisory = async function test() {
const a = await Promise.resolve(1);
const b = await Promise.resolve(2);
return a + b;
};
References:
4. Further reading:
You-Dont-Know-JS, Async and Performance, Chapter4: Generators