
Jordan Kasper | @jakerella
Not quite.
Promises are a mechanism for managing callbacks.
https://en.wikipedia.org/wiki/One_Ring
...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 }
yieldReceiving 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()doneyielded 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