What is Callback Hell
Using your own code as an example. We can see that the callback hell is defined by this pyramid at the end of })
. Simply awful.
Follow the passage:
})
}.bind(this))
}
})
})
}
})
How can I avoid?
The only way to avoid the hell of callbacks is by keeping good practice in your codes. Being these practices
1. Keep Code Clean and Easy
This is an example of a code that clearly is bad.
var form = document.querySelector('form')
form.onsubmit = function (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, function (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
})
}
Let’s name the functions
var form = document.querySelector('form')
form.onsubmit = function formSubmit (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, function postResponse (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
})
}
Naming functions has immediate benefits such as:
- Makes the code easy to read thanks to the description of the function in their names,
above we have postResponse and formSubmit, which are self-explanatory.
- When exceptions occur you will get more informative traces of
where the problem is directly in the functions, rather than strangers
"Anonymous".
- Allows you to reference your functions.
Finally you can move the functions to the top of the program and will hardly have problems with the hell of the callbacks.
document.querySelector('form').onsubmit = formSubmit
function formSubmit (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
}
2. Modularize
Anyone who makes a correct modularization of the code will hardly have trouble with the hell of the callbacks
.
Creating a file called formuploader.js
that contains our two functions
previous, we can use the module.exports
to modularize everything:
module.exports.submit = formSubmit
function formSubmit (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
}
In Node.js we have the famous require, but we can also use this require in our browser with Browserify. So we have access to require, and can call the module we created in the file formuploader.js
and then using the created module.
var formUploader = require('formuploader')
document.querySelector('form').onsubmit = formUploader.submit
And now we have two vital advantages. Being two of them:
- Easy to read by new developers
- formuploader can be used elsewhere.
3. Avoid any errors
Sure mistakes can happen, you need to make sure they don’t go through the code without you knowing where they are. Many callbacks are built with an argument that helps us deal with these errors.
For example:
var fs = require('fs')
fs.readFile('/Does/not/exist', handleFile)
function handleFile (error, file) {
if (error) return console.error('Uhoh, there was an error', error)
// otherwise, continue on and use `file` in your code
}
note the error argument being treated in return console.error('Uhoh, there was an error', error)
extremely important if any problem occurs.
More About Callback Hells or Callbacks Hell
I have no interest in answering, so I’ll just comment that this happens because people look for the most complicated ways. Interestingly the more experienced who could handle it better avoid abusing a resource that was made for thrifty use.
– Maniero
But then there’s no point in using callbacks?
– Artur Trapp
This way I think not, if to change that is
for
the language is much simpler and has no problem at all. probably even thereaddir
would not need it, but if using it alone does not cause the reported problem. Of course it has advantage in specific cases, not abuse. Almost always aforEach()
is a mistake.– Maniero
"Almost always a foreach() is a mistake." You could explain that statement better?
– Marcell Alves