The Section 2: Functions & Methods of my JavaScript Core Concepts Series is divided into 6 Parts:
Part 1 Functions
Part 2 Classes
Part 3 Methods
Part 4 Callback Functions
Part 5 Scope
Part 6 Hoisting
Callback Functions
Part 1 What is a Callback Function?
= Callback
: Name of a JS Function Convention
→ Not a tool w/ unique functionality
Here are a few definitions:
Function executed
= At end of execution of another functionFunction passed into another Function as an Argument
= To be executed laterFunction that runs asynchronously
Functions = Objects in JS
= They can take Functions as Arguments
→ & Can be returned by other Functions
Difference between Callbacks & most Functions
= Callbacks do not immediately return some result
→ They take time to product a result
Higher-Order Function
= Function that takes other functions as arguments
→ Function being passed in: Called a Callback Function
Code Example
const button = document.querySelector(‘button’)
button.addEventListener(‘click’, function(e) {
this.classList.add(‘clicked’)
})
= JS listening for click
event on button
→ Only calls the function in 2nd argument if event is detected
…
Part 2 What is the purpose of a Callback Function?
Store things to do at later time
= Order in which events occur: Does not work top-to-bottom
→ Skips around depending on when things completeDealing with tasks that get dispatched
= Go off and do something in the background
→ Then, complete successfully or abort due to failure
Callbacks are used in 2 different ways:
1st Way: Synchronous Functions
= Code is synchronous
→ If executes top-to-bottom, left-to-right, sequentially
→ Waiting until 1 line of code finishes
Before next line begins
→ Process continues until last line of code is executed
Callbacks in Synchronous Functions
= When want a part of code to be easily swapped w/ something else
Code Example
const numbers = [10, 11, 19, 40]
const getLessThanFifteen = num => num < 15
const getMoreThanTwenty = num => num > 20
const lessThanFifteen = numbers.filter(getLessThanFifteen)
const moreThanTwenty = numbers.filter(getMoreThaTwenty)
Normal vs Async Functions
Normal Functions
= Allow you to use its return value
Async Functions that use callbacks
= Don’t return anything straight away
Waiting for Response
= Don’t want program to pause
→ So you store the code that should run afterwards
Inside a Function: Called a Callback Function
2nd Way: Asynchronous Functions
= Takes some time, happens in the future, not right now
→ JS needs to wait for something to complete
→ Will run rest of tasks given to it: While waiting
Code Example
= Asynchronous Function that takes a Callback to execute at later time
const twentySecondsLater = () => console.log(‘20 seconds passed!’)
setTimeout(twentySecondsLater, 20000)
console.log(‘Start!’)
= JS executes setTimeout
→ Then it waits for 20 seconds
→ And then logs ‘20 seconds passed!’
= Same time as waiting for setTimeout
to complete in 20 seconds
→ JS executes `console.log(“Start!”)
…
Part 3 How do you create a Callback?
= There are 2 ways to create Callbacks:
1st Way: Anonymous Functions
Pass Callback Function Definition as an Argument
Define it in the Function Call
To do this, you pass in
callback
as the last Parameter of the FunctionThen the Callback Function itself is defined in the 2nd Argument during the Function Call
Code Example
The event on ${date} has been created.`);
function createEvent(date, callback) {
console.log(
callback();
}
createEvent(“September 22nd, 2022”, function() {
console.log(The event is being displayed.
)
})
`
2nd Way: Named Functions
Pass reference to Callback as an Argument
Or you can define the Callback Function elsewhere
= & Pass its reference as the 2nd Argument during the Function CallYou can also pass in any amount of arguments that the callback may need
= & Arguments passed into Callbacks
→ Make their way through to the Callback
Code Example
The event on ${date} has been created.`);
function createEvent(date, callback) {
console.log(
callback();
}
function displayEvent(){
console.log(The event is being displayed.
);
}
createEvent(‘September 22nd, 2022’, displayEvent);
`
…
Part 4 What do Callbacks look like in-action?
= Asynchronous Callbacks are useful as a Solution to Blocking Behavior
= Usually used when there is a transfer of data when doing I/O
→ ie Downloading things, reading files, talking to database, etc.
Callback Queue
= Everything in the Stack is ran before moving onto the Callback Queue
→ Anything in a setTimeout()
is ran with the Callback Queue
→ This means that even if something in the Callback Queue is never completed, the code keeps running
Is the Callback Queue for all Callbacks or only Async Callbacks?
Common Use Cases
When an event fires
= Event listeners
ieaddEventListener
After AJAX Calls
= jQuery’s ajax method
iejQuery.ajax
After reading or writing to files
= Node, ExpressJS
iefs.readFile
Purpose of Callbacks
= Ensure response of Function is received/finished executing
→ Before executing other code
Example Use Case
= Make Requests to an API
→ Need to wait to receive a Response from Server
To act based on Response
→ Do not know if API Request is going to be successful
Code Example
T.get(’search/tweets’, params, function(err, data, response) {
if(!err){
// What to do if API request successfully executes
} else {
console.log(err);
}
})
= After Response received
→ Callback is invoked
→ Twitter will either send an err
Object
Or a response
Object back to us
= Conditional w/in Callback
→ Uses Information
To determine if Request was successful or not
Then act accordingly
…
Part 5 What are the problems with Callbacks?
The biggest problem with Callbacks is Callback Hell
What is Callback Hell?
= Multiple Callbacks nested after each other
→ ie Doing an asynchronous activity
That depends on previous asynchronous activity
Example Scenario
= Usually, Callback Hell is found in the Backend
→ While using Node
→ Rare to see Callback Hell in Frontend JavaScript
= Pyramid shape with numerous })
s at the end
→ Result of attempts to write JS so execution occurs chronologically
→ In JS, what occurs on 1st line will not necessarily finish before code in next line starts running
ie Async functions, setTimeout()
s (which get ran after the call stack)
Why are Nested Callbacks bad?
= Code much more difficult to read
What is the solution to Callback Hell?
= To prevent Callback Hell, you can do these things:
1. Write Shallow Code
#1 Do not nest Anonymous Functions
= Name all Functions
→ Use Functions through reference to Names
→ Rather than writing out elaborate logic of anonymous function
→ Code will be easier to understand → B/c descriptive Names
If exceptions occur
= Have Stack Traces w/ Function Names
→ Bugs are easier to investigate
#2 Place all Functions at top-level program (‘below the fold’)
= Take advantage of Function Hoisting
→ Move all Functions to bottom of File
→ Then, move into another File: When & If the load demands
2. Modularize
#1 Write small Modules
= That each do 1 thing
→ Compile them into other Modules that do a bigger thing
→ ie Split code into couple of Files
#2 Isolated Files
= Used by loading them through a relative require()
→ Then, can move Functions into standalone Module
Code Example
= Create a new File for a series of Functions
→ Performing related functionality
ie Module named useruploader.js
`
module.exports.create = userCreate
function userSubmit (submitEvent) {
var name = document.querySelector(‘input’).value
request({
uri: “http://example.com/upload”,
body: name,
method: “POST”
}, postResponse)
}
function postResponse (err, response, body) {
var statusMessage = document.querySelector(‘.status’)
if (err) return statusMessage.value = err
statusMessage.value = body
}
`
module.exports
= Example of Node.js Module System
→ Works in Node, Electron & Browser
Benefit of module.exports
= This style of Modules is good because it works everywhere
→ Easy to understand
→ Does not require complicated config files or scripts
Using module.exports
Modules
= After File is created
→ You need to require it
→ & Use it in your application specific code
Code Example
var userUploader = require(‘useruploader’)
document.querySelector(‘form’).onsubmit = userUploader.submit
Benefits of Modularising
1. Comprehensibility
= Code required in app is only 2 lines
→ Allows new devs to more easily understand you code
→ Won’t need read through details of all Functions w/in Module: When trying to grasp what Program is trying to do
2. Error-handling, test-writing, creating a stable and documented public API
3. Refactoring
4. Reuse
= W/o duplicating code
→ Can easily be shared on Github or npm
How do you create good Modules?
1. Move repeatedly used code into a Function
2. When Function/group of Functions gets large enough
= Move them into another File
→ Expose them using module.exports
→ Which can be loaded w/ a relative require
3. Code that can be used across multiple projects
= Give it a Read.me, tests, and package.json
→ Public it to Github & npm
4. A Good Module
= Small & focuses on 1 problem
5. Module Should Not
= Have > 1 level of nested Folders full of JS Files
→ If it does: It is likely doing too many things
6. Reference Examples of Good Modules
= Get a good idea of what they look like
7. If Module takes > a few minutes to understand
= Not Good
…
Part 6 How should Callbacks be used?
= Write Stable Code
= Handle Every Error
→ You should handle every single error
→ In Every One of your Callbacks
How can you handle every error?
a. Plan on errors always happening
= Can never know when Errors happens
→ Must make code stable
b. Node.js Style
= 1st Argument to Callback
→ Always reserved for an Error
→ Use error
as 1st Argument Convention
→ Instead of adding it as the 2nd Argument
= Reminds you to handle your errors
c. Code Linters
= Help remind you to handle Callback Errors
→ Show you every Callback in your code
→ With an Unhandled Error
Types of Errors
#1 Syntax Errors
= Caused by Programmers
→ Usually caught when trying to 1st run program
#2 Runtime Errors
= Caused by Programmer
→ Code ran, but had a bug that caused something to mess up
#3 Platform Errors
= Caused by
→ ie Invalid File Permissions, Hard Drive Failures, no Network Connection etc.
...
Resources for Further Exploration:
JavaScript: What the heck is a Callback? By Brandon Morelli
Callback Hell: A guide to writing asynchronous JavaScript programs
What the heck is the event loop anyway? | Philip Roberts | JSConf EU
Top comments (0)