I thought to discuss simply the differences between callbacks and promises in JavaScript and why promises are becoming so popular.
The classic callback pattern
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function getDataCallback(apiUrl, callback) { // If the callback is successful // pass the err parameter as "undefined" callback(undefined, {"your": "JSON object"}); // If the callback was unsuccessful // pass the error message callback("No data found"); } getDataCallback('http://your-api.com', function (error, data) { // If err is not undefined if (error) { console.log('There was an error:', error); } else { console.log('It worked', data); } }); |
In the callback you check if there is an error and if not, you process the success. It works and has worked for a while, but there are a few problems with this pattern.
First, you have duplication by having to call the callback function for both a success case and a error case.
Second, you have one function handling multiple cases – the callback has to manually check if there is an error and handle it. Every time you need to manually do that and the code starts to look messy and confusing the more you add.
Third, you can end up (for whatever reason) calling the callback function multiple times for either success or errors. This can cause all sorts of issues.
Promises
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function getDataPromise(apiUrl) { return new Promise(function (resolve, reject) { // If the callback is successful resolve({"your": "JSON object"}); // If the callback was unsuccessful reject('No data found'); }); } getDataPromise('http://your-api.com').then(function (data) { // Handle successfully returned data console.log('It worked', data); }, function (error) { // Handle errors console.log('There was an error:', error); }); |
You can call each only once and this is a much cleaner way, there are no assumptions (“undefined” means error).
Next, the promise function is called and it has a method available called .then(); The first parameter of .then() always handles the success so you know you will receive whatever you were expecting (in this case our JSON object “data”). The second parameter of .then() handles fails, hence the “error” is passed to receive the respective error.
You could achieve this pattern yourself as well, but promises provide a secure and intuitive way of handling callbacks.
Conclusion
Promises are great as they provide an easy, simple and secure way to handle callbacks in ES6, that is readable and just makes sense. If you want to read more on promises, check this article by Jake Archibald on developers.google.com.