


Inversion of Control in JavaScript Callbacks: Why Promises are the Answer
A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. There are two ways in which the callback may be called: synchronous and asynchronous. It is the most fundamental async pattern in Javascript.
For example:
A and B happen now, under the direct control of the main JS program. But C gets deferred to happen later, and under the control of another party, in this case, the ajax(..) function. In a basic sense, that sort of hand-off of control doesn’t regularly cause lots of problems for programs.
However, infrequency is not sufficient to ignore the problem or issue. In fact, it’s one of the major problems of callback-driven design. It revolves around the idea that sometimes ajax(..) or the “party” you pass your callback continuation to is not a function that you wrote, or that you directly control. Many times it’s a utility provided by some third party.
We call this “inversion of control” when you take part of your program and give over control of its execution to another third party. There’s an unspoken “contract” that exists between your code and the third-party utility — a set of things you expect to be maintained.
What is the problem with “Inversion of Control”?
There is an example for better understanding this problem.
Let’s say you’re building a travel booking website for your company. You’ve added a “book now” button that uses a third-party library’s createBooking() function. This function processes the booking and then calls your callback to send a confirmation email to the customer.
This code might look like:
Everything works perfectly during testing. People start booking travel packages on your website, and everyone is happy with your work. Suddenly, one day, you get a call from your boss regarding a major issue. A customer booked a package and received four identical confirmation emails for one booking.
You start debugging the issue. You review the part of the code that sends the confirmation email, and everything seems correct. You then investigate further and find that the createBooking() utility from the third-party library called your callback function four times, resulting in four confirmation emails being sent.
You contact the third-party library’s support team and explain the situation. They tell you they have never encountered this issue before but will prioritize it and get back to you. After a day, they call you back with their findings. They discovered that an experimental piece of code, which was not supposed to go live, had caused the createBooking() function to call the callback multiple times.
The issue was on their side, and they assured you that it has been fixed. They apologized for the trouble and confirmed that the problem would not occur again.
To prevent any unwanted issue like that after some seeking for a solution, you implement a simple if statement like the following, which the team seems happy with:
But then one of the QA engineers asks, “what happens if they never call the callback?” Oops. Neither of you had thought about that!
You start to think of all the possible things that could go wrong with them calling your callback. Here is a list of some of the problems:
Call the callback too early
Call the callback too late (or never)
Call the callback too few or too many times (like the problem in the example above)
Swallow any errors/exceptions that may happen
...
You will probably realize that you have to implement many solutions in your code for different situations, which will make the code awful and dirty because it is required in every single callback passed to a utility.
Promises
What if we could uninvert that inversion of control? What if instead of passing the continuation of our program to another party, we could expect it to return us a capability to know when its task finishes, and then our code could decide what to do next?
Promises offer a powerful way to handle asynchronous operations in JavaScript, addressing issues like callback hell and inversion of control. Unlike callbacks, Promises lets you manage asynchronous tasks without giving up control of your code.
Consider ordering a cheeseburger at a fast-food restaurant. You receive a receipt, a promise of your future cheeseburger. While you wait, you can do other things, knowing you’ll get your order eventually. Similarly, a Promise in JavaScript represents a future value, allowing your code to proceed smoothly.
Promises also handle failures gracefully, just as you might be informed if the restaurant runs out of cheeseburgers. This structure makes your code more readable and maintainable.
I’m not going to go in depth into Promises here, but by using them, you can write cleaner, more reliable asynchronous code, improving the overall quality of your JavaScript applications.
For example, for the travel booking website we described earlier, if the third-party utility returns a promise we can handle it like this:
Once a Promise is resolved (successfully completed), it stays that way forever — it becomes an immutable value at that point and can then be observed as many times as necessary. That means a resolved promise, its resolved value can be accessed or used multiple times in your code without affecting its state. This allows you to handle the result of the asynchronous operation in various parts of your application without worrying about the Promise changing or being re-evaluated.
Promises are a solution for the inversion of control issues that occur in callback-only code. Callbacks represent an inversion of control. So inverting the callback pattern is actually an inversion of inversion, or an uninversion of control. Restoring control back to the calling code where we wanted it to be in the first place.
References
You Don’t Know JS: Async & Performance by Kyle Simpson
developer.mozilla.org
The above is the detailed content of Inversion of Control in JavaScript Callbacks: Why Promises are the Answer. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.
