Skip to content

Instantly share code, notes, and snippets.

@hackergrrl
Created March 2, 2017 22:28
Show Gist options
  • Save hackergrrl/6ba3e5ceb6e7b9f93620fdca2b4eb23f to your computer and use it in GitHub Desktop.
Save hackergrrl/6ba3e5ceb6e7b9f93620fdca2b4eb23f to your computer and use it in GitHub Desktop.

understanding callbacks & async code flow

Consider setTimeout: a very simple asynchronous function. It takes two parameters: a callback and a delay:

setTimeout(fn, delay)

In use, it might look something like this:

setTimeout(onDone, 1000)

function onDone () {
  console.log('done')
}

You can try running this by saving it into a file named e.g. timeout.js and then running node timeout.js. Remember that the following is equivalent to what's above, with the function inlined as a parameter:

setTimeout(function () {
  console.log('done')
}, 1000)

I could create a module called wait_and_announce.js that wraps this functionality:

module.exports = function (delay) {
  setTimeout(function () {
    console.log('done')
  }, delay)
}

It could be used in another file like this:

var waitAndAnnounce = require('./wait_and_announce')

waitAndAnnounce(2000)

This would wait for 2 seconds and then write done.

What if I wanted to write another message once it completes? Like huzzah!? Maybe I could just do..

var waitAndAnnounce = require('./wait_and_announce')

waitAndAnnounce(2000)

console.log('huzzah!')

If you run this, you'll see

huzzah!
done

Why did huzzah! come first?

When you run an asynchronous function (like setTimeout), generally its code will run at some point "in the future", and regular code execution continues. You can see this here: setTimeout gets called in wait_and_announce.js and then console.log('huzzah!') runs. Then, at some point later, the timeout finishes and the function inside setTimeout runs.

To run code AFTER an asynchronous function runs, we can give it a "callback". This is a function object that the function you're giving it to can run once it's finished. In fact, the function I handed to setTimeout is a callback.

Here's wait_and_announce again, but with a callback as a parameter that's called once the function is finished:

module.exports = function (delay, callback) {
  setTimeout(function () {
    console.log('done')
    callback()
  }, delay)
}

Now I can modfy my original main program like so, to write huzzah! after done:

var waitAndAnnounce = require('./wait_and_announce')

waitAndAnnounce(2000, onDone)

function onDone () {
  console.log('huzzah!')
}

Run it; you'll see done followed by huzzah!. Like before, this is equivalent to inlining the callback:

var waitAndAnnounce = require('./wait_and_announce')

waitAndAnnounce(2000, function () {
  console.log('huzzah!')
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment