300 JavaScript: Writing asynchronous code [2.5d]

Updated . Posted . Visible to the public.

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.

Profile picture of Henning Koch
Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra Curriculum (2015-08-20 15:01)