AJAX (Asynchronous JavaScript and XML), which gained serious traction in mid-2000s, is a set of techniques consisting of sending asynchronous (hence “A”) requests between the browser and the application server, containing XML objects (hence “X”) with the use of JavaScript (hence “J”) and allowing dynamic content changes without the need of reloading the whole page. At the very heart of the AJAX’s API object lies a powerful XMLHttpRequest that gives us the power to retrieve the data (any data, not just XML obviously) from the server and then process it client-side. After the advent of many JavaScript abstractions, biggest of them all being of course jQuery, utilisation of AJAX required less and less effort making this technique still relevant as of today. And this is why we’ll talk about the AJAX in the conjuction with jQuery events, or to be more precise - how to make parallel AJAX requests using ‘beforeSend’ and ‘complete’ events.

Our application relies heavily on external API calls that allow collecting data which is then saved to the users table in our database. This synchronization takes place at several points in app’s “runtime”, one of which occurs during login process. Let us examine the simple AJAX login method.

(A little disclaimer - in our code we are using ‘js-routes’ gem, which allows us to use helper-like paths in our js files)

It’s pretty straightforward - we prevent the submit action, serialize form data, then send the request to our controller which then checks credentials and whatnot, ultimately resulting in JSON containing our error message or, in the case of success, the call to the function responsible for data collection from external APIs and redirection to the home page. This function will consist of two AJAX calls hitting controllers responsible for HTTP calls to respective APIs (let’s call them api1 and api2). Single request would look like this:

On its own it would be as simple as that, but we have the other controller to hit. We could do something like this:

The problem with this solution is that the second function has to wait for the previous request to resolve and the strength of AJAX’s asynchronicity is lost. What we need is to make these requests parallelly and redirect only after both are resolved. This is where ‘beforeSend’ and ‘complete’ events come in handy. First one occurs before the request is sent, second one after it is fully resolved, whether it was successful or not. In this case, we technically could forego the ‘success’ event completely cause we want our user to be redirected to home page regardless of our functions results, since we cannot lock them out of the page because of the external API’s downtime. One thing that needs to be resolved is they way we determine when to redirect, or to put it differently - are all of the functions resolved or not. To do this we’re gonna create a counter flag and update it in aforementioned ‘beforeSend’ and ‘complete’ events. So let’s start building our getData function.

First we set our counter to 0, obviously, then proceed with the “first” (it’s not exactly first, since they will proceed parallelly).

Now for our events. What we want to do, is to increment a function_counter as the request starts to indicate that there is one ongoing.

Then, as it completes (again - regardless of it’s success), we decrement the counter, check if all of the requests are resolved (the function_counter equals 0), and if so - redirect user to home page.

And voila. Let’s add the second request now.

We could clear that up by moving the urls to the array and then iterating through it to remove repetition, but I will leave that to you. What we can do, though, is to add `error` events to gather potential errors. We will start with the empty array at the beginning of the function and then push error messages to it in each of the requests ‘error’ event. Then you can pass these messages to redirect function and then as a params to our path, so you can use them to set flash messages for after the user is successfully logged in. Our function should look like this now:

And just like that, our two requests are processed at the same time utilizing the full potential of AJAX.