Effective Ways to Remedy Race Conditions

Effective Ways to Remedy Race Conditions

Race conditions are a persistent issue that have plagued programmers since the very beginning. Initially, they were related to hardware and the technology available at the time, but they now manifest in different ways. One of the more prevalent places where race condition issues occur is in the JavaScript code that runs on the client’s browser. These issues can be identified through irregularities in the output from a part of the code base that can’t be explained even by faulty logic. In this post we will talk about a few ways to spot a race condition issue (also sometimes referred to as a timing issue) and some ways they can be handled. Since most of our projects use jQuery, we will be citing examples from that library.

Identifying Issues

When debugging is an issue, one of the most frustrating problems is when the root cause isn’t easily identifiable. Most of the issues we see that are race condition related are due to elements not loading fast enough on the page, or other functions not returning fast enough for other parts to then execute properly. These issues come from things like appending a lot of html using a library’s function: like the execution speed of append from jQuery vs innerHtml from native JavaScript. The average execution time for the innerHtml function is a fraction of the append function in jQuery, so make sure to keep that in mind. Most of the time a few milliseconds aren’t that important, but when you are loading a page, it can make or break your js code.
One of the quickest and simplest ways to fix a race condition issue is to move the script that isn’t functioning properly to a later section of the page in the execution order. A more targeted fix is recommended, but when you need something quick, this is one of the best methods – as long as the timing based issue isn’t held up by an asynchronous method to finish.

Solving Issues

Another common example of a race condition issue comes when an ajax call doesn’t complete before other methods that rely on its return data are called.
These kinds of situations are difficult to fix because the issue isn’t typically with the code that is immediately related to that part of the site. One way of handling asynchronous issues is to wrap the code that’s not executing properly in a custom event handler, which can then be fired from the end statement of a function like an async ajax call. A more complicated fix would be needed if the code that is not executing properly is wrapped in a $(document).ready handler.
Another option is to use the $.holdReady(state) function. If you call $.holdReady(true) the document ready function will be locked. Once the code that is not returning when expected has completed, use $.holdReady(false) to unlock the document ready handler and allow the rest of the code to complete. The only downside to the latter method is when a lot of functions or jQuery plugins are added at document ready, the holdReady function can cause other issues.
Example 1: Using a custom event to ensure the data has returned before trying to use it.

Example 2: Using the holdReady function to prevent the data from being used before it’s there.

Now that hardware specs have vastly improved, one of the most common places where you will run into race condition issues is in the client side JavaScript of a browser. While most machines can handle a web app, the resources allocated for the browser may not, and the root cause can be hard to identify. Hopefully these tips will help you mitigate the challenges the next time you come across race condition issues.