Concurrency challenges with this model
We'll wrap this chapter up with a discussion on the challenges that this execution model poses with JavaScript concurrency. There are two fundamental obstacles. The first is the fact that no matter what, any JavaScript code that runs will block anything else from happening. The second obstacle is trying to synchronize asynchronous actions with callback functions, leading to callback hell.
Limited opportunity for parallelism
It used to be that the lack of parallelism in JavaScript wasn't really an issue. Nobody missed it because JavaScript was viewed as a progressive enhancement tool for HTML pages. This changed when the front-end started taking on more responsibilities. These days, the majority of the application actually resides in the front-end. This allows back-end components to focus on problems that can't be solved by JavaScript (from a browser perspective, NodeJS is another matter entirely that we'll look at later in the book).
For example, mapping and reducing API data sources into some representation required by a feature can be implemented in the back-end. This means that the front-end JavaScript code just needs to query for this endpoint. The problem is that this API endpoint is created for some specific UI feature, not as an essential supporting pillar of our data model. If we can perform these tasks in the front-end, we keep the UI features and the data transformations they need, tightly coupled together. This frees up the back-end to stay focused on more pressing issues like replication and load balancing.
We can perform these types of data transformations in the front-end, but they wreak havoc on the usability of the interface. This is largely due to all the moving parts competing for the same compute resource. This model, in other words, makes it impossible for us to implement the parallelize principle and take advantage of more than one resource. We will overcome this web browser limitation with the help of Web workers, covered in further chapters.
Synchronization through callbacks
Synchronization through callbacks is hard to implement and doesn't scale well. It's callback hell, which is a term popular among JavaScript programmers. Needless to say, endless synchronization through callbacks in our code creates problems. We often have to create some kind of state tracking mechanism, such as global variables. And when problems do arise, a nest of callback functions is very time consuming to traverse mentally.
Generally speaking, the callback approach to synchronizing multiple asynchronous actions requires a lot of overhead. That is, the boilerplate code that exists for the sole purpose of dealing with asynchronous actions. The synchronize concurrency principle is about writing concurrent code that doesn't embed the main goal in a maze of synchronization handling logic. Promises help us write concurrent code consistently throughout our application by lessening the use of callback functions.