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!')
})