×
By the end of this chapter, you should be able to:
In ES2015, a special type of function called a generator was introduced. Generator functions are functions that can return
multiple values using the yield
keyword. Previously, we have only seen functions that return
once, but generators can change that for us. Let's start with a simple generator example (generator functions are denoted using a *
):
function* firstGenerator() { for (var i = 0; i < 5; i++) { yield i; } } var gen = firstGenerator(); gen.next(); // {value: 0, done: false} gen.next(); // {value: 1, done: false} gen.next(); // {value: 2, done: false} gen.next(); // {value: 3, done: false} gen.next(); // {value: 4, done: false} gen.next(); // {value: 5, done: true} // we can also iterate over a generator using a for..of loop for (var data of firstGenerator()) { console.log(data); } // 0 // 1 // 2 // 3 // 4
Let's now see what our earlier async example would look like if we used generators:
function getJokesAbout(term) { $.getJSON( `https://icanhazdadjoke.com/search?term=${term}`, function(data) { // we could also do gen.next(data) to make this function run all three at once console.log(data); }, function(err) { console.log(err); } ); } function* displayResults() { var result1 = yield getJokesAbout("spider"); console.log(result1); var result2 = yield getJokesAbout("ghost"); console.log(result2); var result3 = yield getJokesAbout("pizza"); console.log(result3); } var gen = displayResults(); // if we want to print all without using next() for (var jokeData of displayResults()) { console.log(jokeData); }
While this may seem simple to look at, generators are not always the easiest to read and can add a great deal of complexity quickly.
A better option is to use ES2017 async
functions.
As of ES2017, two new keywords have been added to the language: async
and await
. These two keywords allow us to write code that "looks" synchronous, but is actually asynchronous. We prefix our functions with the async
keyword to denote that they are actually asynchronous and we invoke those functions with the keyword await
to ensure that they have completed before their values are stored. These keywords are actually not new to programming languages; both Python and C# have the same concept.
async
and await
are relatively new additions to the language, so in order to run all of these code examples, make sure you're using Node version 7.6 or higher, or are working in a modern browser (the most recent version of Chrome will suffice).
Note that when you make a funciton an async
function, it automatically returns a promise to you. Very commonly you'll create the promise yourself, but even if you don't, the value you return will be wrapped in a promise:
async function asyncExample() { return 1; } asyncExample(); // PromiseĀ {<resolved>: 1}
Let's revisit our example from before, but refactor it one more time to use async
and await
! Try this out in the browser:
// Using Promises alone async function logJokesAbout(term) { var data = await $.getJSON(`https://icanhazdadjoke.com/search?term=${term}`); console.log("Here is the joke data!", data); } logJokesAbout("spider"); logJokesAbout("pizza"); // etc.
Remember: if you return the data rather than logging it, you'll get a promise, not the actual data!
For more on async
and await
, check out the MDN guide to async functions.
When you're ready, move on to Asynchronous JavaScript Exercises