Jordan Kasper | @jakerella
Not quite.
Promises are a mechanism for managing callbacks.
...but it doesn't really get us where we want to be.
A mechanism for pausing (and resuming)
function execution.
Long run complete
100 ms timeout!
This code runs without stopping to the end...
setTimeout()
causes an asynchronous callback after 100 ms...
...but this for
loop will block the event loop until it's done.
Generators allow functions to pause and resume execution!
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
And this is how you execute it...
Inside foo
Outside foo
Back inside foo
Notice that my generator "yielded" two values:
Call the next()
one last time...
{ value: 'a', done: false }
{ value: { b: 2 }, done: false }
{ value: undefined, done: true }
Adding a return
statement:
const genObj = foo();
console.log( genObj.next() );
console.log( genObj.next() );
console.log( genObj.next() );
{ value: 'a', done: false }
{ value: { b: 2 }, done: false }
{ value: 'c', done: true }
In fact, we can iterate (or loop) over them!
a
{ b: 2 }
yield
Receiving input from a yield
We just throw
and catch
Error objects.
If an error occurs outside the generator...
Oops! I did it again.
If an error occurs inside the generator...
Caught outside generator: Nope nope nope.
Generators (Obviously) and Promises
Easy, just promisify
the function!
function promisify( callbackStyleFn ) {
return function promiseStyleFn(originalArg) {
return new Promise(function( resolve, reject ) {
callbackStyleFn(originalArg, function(err, value) {
if (err) { return reject(err); }
resolve(value);
});
});
};
}
(Warning: do not use this code!)
next()
to start itvalue
off the yielded objectnext()
over and overgen.throw()
We want to abstract away their "Iterable" nature...
next()
done
yield
ed Promise to resolve / reject
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
(Warning: do not use this code! It is not complete.)
{ "foo": "bar", "nextIndex": 2, "message": "Generators" }
{ "foo": "bat", "nextIndex": 5, "message": "are" }
{ "foo": "baz", "nextIndex": null, "message": "cool" }
{ "foo": "bar", "nextIndex": 2, "message": "Generators" }
100 ms timeout!
{ "foo": "bat", "nextIndex": 5, "message": "are" }
{ "foo": "baz", "nextIndex": null, "message": "cool" }
ERROR! ENOENT, open 'data-infinity.json'
Retrieved data: [ '{ "foo": "bar", "nextIndex": 2 }',
'{ "foo": "bat", "nextIndex": 5 }' ]
async
and await
async function getData() {
try {
const one = JSON.parse(await readFile('data-1.json'));
const two = JSON.parse(await readFile('data-' + one.nextIndex + '.json'));
const three = JSON.parse(await readFile('data-' + two.nextIndex + '.json'));
} catch(err) {
// Handle the error...
}
}
Because it is!
async
functions are based on "pausing" in generators
and await
requires a Promise!
... aaaah, but how long until I can use this?
Jordan Kasper | @jakerella