GladstoneKeep
GladstoneKeep

Reputation: 3972

Can this ever be a race condition? (JavaScript)

I'm looking for a solid answer on whether the following JavaScript code contains a race condition or not.

The question boils down to this: If I begin listening for the completion of an asynchronous task (such as an AJAX call) immediately after I've initiated the task, could that task complete before I've started listening?

I've found a few similar questions, but none has an answer that seems totally concrete ("there could be a problem ... it is unlikely that..."). Here's a rough example of the kind of situation I'm referring to:

// Publish an event synchronously
function emit(key){}

// Subscribe to an event
function on(key, cb){}

// Request the given url;
// emit 'loaded' when done
function get(url) {
  http.get(url, function() {
    emit('loaded');
  });
}

get(url);

on('loaded', function() {
  // Assuming this subscription happens
  // within the same execution flow as
  // the call to `get()`, could 'loaded'
  // ever fire beforehand?
});

Even better if the answer has backing from the actual language specification (or another definitive source)!

Upvotes: 1

Views: 70

Answers (2)

Seth
Seth

Reputation: 46423

@Guffa is correct. But, there are at least two situations where you can have the appearance of a race condition.

Maybe there is an error during the ajax request that isn't handled. Consider some typical XMLHttpRequest code:

var request = new XMLHttpRequest();
request.onreadystatechange = function() {
    if (request.readyState === 4) {
        if (request.status === 200) {
            call_success_handler();
        }
        else {
            call_error_handler();
        }
    }
};

request.open("GET", url , true);
request.send(null);

If the readyState is never '4', then no handlers will be called and no errors will be reported. Your success handler is never triggered, so you assume that the event fired too fast and you didn't notice.


It's less common now, but there are also cases where browsers may make you think you have a race condition. The specification says what is supposed to happen in error conditions, but it wasn't always that way. Old / non-conforming XMLHttpRequest implementations behave poorly with oddball network conditions. The initial (ca. 2006) versions of the spec didn't even address network level errors.

Hopefully most browsers have conforming implementations now, and hopefully most frameworks should handle error conditions properly.


There's a great article by Pearl Chen on asynchronous debugging that's worth a read if you want to dig into it deeper.

Also, there's more information on ajax problems here: jQuery $.ajax, error handler doesn't work.

Upvotes: 1

Guffa
Guffa

Reputation: 700152

No, there can be no race condition.

The asynchronous task could complete before you start listening to the event, but that doesn't matter. The completion of the task creates an event, and that event won't be handled until the function (or code block) ends and the control is returned to the browser.

Upvotes: 4

Related Questions