Rapid ES6 Training:Iterators, Generators and Promises

mark-zamoyta-v1

Welcome to Part 4 of this review of the Pluralsight course Rapid ES6 Training by Mark Zamoyta.

Mark started in the developer world over 25 years ago.

He has written numerous mobile apps and games for clients including Electronic Arts and Yahoo! Games.

Rapid ES6 Training is the final course in the new JavaScript learning path.

The aim of the course is for you to be able to use the new syntax and features of ES6, and the prerequisite is to be familiar with the earlier ES5 version of JavaScript.

Iterators, Generators and Promises

Iterators

We saw the Symbol type in the previous module. In ES6 we can add properties to classes while guaranteeing that the property name is unique.

But what type is Symbol.iterator?

let ids = [9000, 9001, 9002];
console.log(typeof ids[Symbol.iterator] );

Here’s how we can use it:

let ids = [9000, 9001, 9002];
let it = ids[Symbol.iterator]();
console.log(it.next());

Mark explains the result, which seems a little weird at first. What if we do this?

let ids = [9000, 9001, 9002];
let it = ids[Symbol.iterator]();
iter.next();
iter.next();
console.log(it.next());

Finally we see this but calling iter.next() three times.

Now we’ve see that iterators are built into arrays, but we can also make our own iterators. Mark shows us an example of this:

let idMaker = {
    [Symbol.iterator]() {
        let nextId = 8000;
        return {
                next() {
                    return {
                        value: nextId++,
                        done: false
                    };
                }
          };
    }
};
let it = idMake[Symbol.iterator]();
console.log(it.next().value);
console.log(it.next().value);

We also see how to use this in a for of loop, and a slightly more complicated example that outputs the same values.

Mark also explains the relationship between iterators and the spread operator:

let ids = [8000, 8001, 8002];

function process(id1, id2, id3) {
    console.log(id3);
}

process(...ids);

Generators

A generator is a special kind of function which is able to yield and get called multiple times. We begin a function name with the * character to denote that it is a generator:

function *process() {
    yield 8000;
    yield 8001;
}
let it = process();
console.log(it.next());

Mark explains that the result of a generator is an iterator, and that’s what we’re assigning to the variable it here.

We are taken through similar examples with heavier use of it.next(), and then see some slightly more realistic examples.

Yielding in Generators

Mark explains that we don’t need to specify a value to yield. I don’t know why you would want to do this, but you can:

function *process() {
    yield;
}
let it = process();
console.log(it.next());

A bit more illustrative is this example:

function *process() {
    let result = yield;          console.log(`result is ${result}`);
}
let it = process();
it.next();
it.next(200);

throw and return

Mark begins with a simple generator which yields three values in a try catch block. The logging includes it.throw('foo')

Then we see the same example without the try catch block.

Mark also shows a way to clean up an iterator by using the return function:

function *process() {
    yield 9000;
    yield 9001;
    yield 9002;
}

let it = process();
console.log(it.next().value);

console.log(it.return('foo'));

console.log(it.next());

Promises

Libraries that offer promises include jQuery and Q.

They are a best practice for more maintainable JavaScript.

To learn more about Promises see Advanced JavaScript – Async Patterns

In this lesson, Mark shows an example of the ES6 Promise function. Once the promise is setup, we can use the then function. This function takes two arguments which are each functions themselves, and we can optionally include a value in each of these:

doAsync().then(function (value) {
    console.log('Fulfilled! ' + value);
},
function (reason) {
    console.log('Rejected! ' + reason);
});

Mark explains that these are passed in via the resolve or reject functions. He also shows an example using the catch function.

More Promise Features

Mark shows an example where the argument for the resolve function is another function called getAnotherPromise()

Next we see an example using
Promise.resolve('Some String');

followed by a similar example using
Promise.reject('Some String');

Next Mark explains the all function with this example:

let p1 = new Promise(...);
let p1 = new Promise(...);

Promise.all([p1, p2]).then(
    function (value) { console.log('Ok') },
    function (reason) { console.log('Nope') });

//assume p1 resolves after 3 seconds,
//assume p2 resolves after 5 seconds

We learn that Promise.all waits for all of the promises to complete.

There are a couple of examples where the behavior of p1 and p2 are different.

A great feature is as soon as we get a first rejection returned, the all function is returned – no need to wait for the other promises to be returned as well.

Mark also gives three code examples of Promise.race which is kind of the opposite of the all function: it returns the result of the promise which completes first.

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s