Guilherme Caminha
Guilherme Caminha

Reputation: 324

Javascript / JQuery handling of concurrent / asynchronous calls and data race

I am currently trying to search a bit about how Javascript handles data race in parallel or asynchronous calls. As far as I'm concerned, the only way to make asynchronous stuff on my code is by AJAX calls (correct if I'm wrong!), but I suppose that if there is another way, it will be handled likewise.

So, as an example, suppose that I have this AJAX call:

jQuery.ajax({
    //stuff
    success: function (data) {
        //do some fancy things with some DOM elements
    },
    //possibly more stuff
});

Suppose now that outside that call I am running other things, and I end up doing something with the same DOM element that my success callback deals within my AJAX call (i.e. appending elements on a table at the same time that my success callback tries to do the same thing). On another words, my configuration ends in some sort of a data race.

How does Javascript deals with this? When my AJAX response comes back, will my current running function be preempted so that the AJAX call be executed? Is there something that guarantees me that what I'm doing with my DOM element (or a javascript variable) is some sort of an atomic operation? So in case I need to run a function that must be atomic, how can I tell that to the interpreter?

Also, is there some shielding on Javascript to prevent deadlocks? Say, if I run two parallel AJAX calls and each one depends on the finishing of the other.

Upvotes: 2

Views: 1314

Answers (4)

guest271314
guest271314

Reputation: 1

Try utilizing Promise.race()

var request = function(url) {
  return new Promise(function(resolve, reject) {
    var res = $.ajax({
        url: url,
        type: "GET"
    });
    res.then(function success(data) {
      resolve(data)
    }, function error(jqxhr, textStatus, errorThrown) {
      reject([textStatus, errorThrown])
    })
  })  
};

var promises = Promise.race([
  request("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js")
, request("https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js")
]);

promises.then(function(response) {
 console.log(response)
}, function(error) {
  console.log(error)
});

Upvotes: 1

Arun P Johny
Arun P Johny

Reputation: 388316

Browser - by extension the javascript(where the page is opened) runs like a single threaded application which can do only 1 thing at a time.

Which means that at any point of time, browser can either run javascript/listen for events or run reflow/repait activities.

Since that is the case at any point of time the browser window can execute only 1 function that means when the ajax response comes back if there is a function that is running then the ajax callback will be added to the execution queue which will get executed when the current function is completed.

You can also achieve asynchronous operation by using setTimeout/setInterval even they would not guarantee that the callback will be executed exactly after 1000ms or whatever delay is given, they just says that it will get executed in the nearest slot that is available

Upvotes: 1

Dustin Hayes
Dustin Hayes

Reputation: 236

So for the first question:

Suppose now that outside that call I am running other things, and I end up doing something with the same DOM element that my success callback deals within my AJAX call (i.e. appending elements on a table at the same time that my success callback tries to do the same thing). On another words, my configuration ends in some sort of a data race.

For this you would simple use jQuery's $.Deferred functionality. All $.ajax calls return, what jquery calls, a deferred object. Also known as a promise object. Also known as a future in other languages. This allows you to execute functionality after the request has finished.

var req = $.get(url, successFunc);
req.done(someOtherFunc);

For the second question:

Say, if I run two parallel AJAX calls and each one depends on the finishing of the other.

I think what you're looking for here is $.when, which allows you to run functionality only when a list of requests have resolved.

$.when([req1, req2, req3], function (res1, res2, res3) {});

Upvotes: 1

juacala
juacala

Reputation: 2235

JavaScript doesn't have any built in protection against this. As part of your code design, you need to make sure that you don't get in a situation where you don't know which of two colliding functions is going to execute first.

This takes some planning. You can either put one Ajax call in the callback of another, or you use events and properties to let other functions know if something is ready for processing, or whether some object is being used and so it shouldn't be touched, etc.

Upvotes: 1

Related Questions