JavaScript: Writing asynchronous code [2.5d]

Reading

Understand how asynchronous JavaScript works:

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:

Create three different implementations of your function:

  1. Using callbacks
  2. Using promises and then()
  3. 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.

Henning Koch