Reading
Understand how asynchronous JavaScript works:
- Read Henning's presentation about asynchronous Javascript (there's also a German video Show archive.org snapshot presentation in our shared folder)
- Read about Promises on MDN Show archive.org snapshot and this visualization Show archive.org snapshot
- Read about async Show archive.org snapshot / await Show archive.org snapshot .
- Read about
requestAnimationFrame
Show archive.org snapshot
and
requestIdleCallback
Show archive.org snapshot
- Note that
requestAnimationFrame
can be used to reduce the number of repaints for animations. This might benefit your application performance.
- Note that
- Read Don't throw exceptions from async functions
- What Color Is Your Function Show archive.org snapshot
- Read about canceling promises
- Error handling in event listeners
- Tasks, microtasks, queues and schedules Show archive.org snapshot
- Picking the Right Tool for Maneuvering JavaScript's Event Loop Show archive.org snapshot
Browse the internet to answer the following questions:
- What are "synchronous" or "blocking" APIs versus "asynchronous" APIs?
- Why does
fetch()
not simply return the response from the server? - Why is asynchronous code such a big issue in JavaScript (as opposed to the code we usually write in Ruby)?
- What are "callbacks" in JavaScript? Can you find examples for libraries that use callbacks to deal with asynchronicity?
- What are "promises" in JavaScript? Can you find examples for libraries that use promises to deal with asynchronicity?
- How can you parallelize multiple calls of an
async
function?
Exercises
Judging asynchronous code
Look at the following code:
async function init() {
console.log("first")
await helperFunction()
console.log("fourth")
}
async function helperFunction() {
console.log("second")
await backgroundTask()
console.log("third")
}
// Stub function that resolves after 100 milliseconds, could be an API call
function backgroundTask() {
return new Promise((resolve) => setTimeout(resolve, 100))
}
init()
What happens when you remove the await
of helperFunction
? What happens when you remove the await
of init
? What causes the new behavior?
Now have a look at this sketched usage of asynchronous functions:
const news = await fetchNews()
renderNews(news)
const recentUsers = await fetchRecentUsers()
renderUsers(recentUsers)
Do you agree with the implementation? If not, what could be improved?
atFullSecond()
Create an implementation of setTimeout
that returns a promise rather than taking a callback. Name this new function atFullSecond
, as it should wait for the remaining milliseconds until the next second starts. For example, at 13:23 and 441 milliseconds, atFullSecond(1)
should wait for 559 milliseconds before triggering the callback function.
Internally, it can make use of setTimeout, but the API should be like that:
atFullSecond(2).then(function() {
console.log(`waited until exactly ${new Date}`)
})
new Date().getUTCMilliseconds()
gives you access to the current millisecond offset.
As a bonus, also reject the promise if the caller passes number smaller than one to atFullSecond
.
doubleRandom()
Write a function called doubleRandom
that
- fetches and logs two random numbers from an API
- returns the sum of those two numbers
You can either implement your own API backend or use the free service at api.random.org Show archive.org snapshot . If you chose the the latter, create an account for it and click yourself a "Developer" API key. Then head over to the documentation of the generateIntegers endpoint Show archive.org snapshot . As learning JSON-RPC is out of scope of this card, you may base your client-side implementation on this code:
fetch('https://api.random.org/json-rpc/4/invoke', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '4.0',
method: 'generateIntegers',
params: {
apiKey: ...,
// other params described in the API documentation such as "n", "min" and "max"
}
})
fetch()
Write a function that:
- Fetches a list of records via
fetch()
. For example, fetch the list of our open-source repos from https://api.github.com/users/makandra/repos Show archive.org snapshot . - Inserts the list into the DOM.
- Slowly fades in the list.
- Allows its caller to run code when the fade-in animation is done.
Create three different implementations of your function:
- Using callbacks
- Using promises and
then()
- Using promises and
async
/await
Note that you are expected to use fetch
in every variant, even though it does not offer a callback interface.