这可能是竞争条件吗? (JavaScript的)

时间:2014-12-25 18:25:24

标签: javascript asynchronous

我正在寻找关于以下JavaScript代码是否包含竞争条件的可靠答案。

问题归结为:如果我在发起任务后立即开始侦听异步任务(例如AJAX调用)的完成,那么该任务是否可以在我完成之前完成我开始听了吗?

我找到了一些similar questions,但没有一个答案看起来完全具体(“可能成为一个问题...... 不太可能那...“)。这是我所指的那种情况的一个粗略的例子:

// 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?
});

如果答案得到实际语言规范(或其他权威来源)的支持,那就更好了!

2 个答案:

答案 0 :(得分:4)

不,没有竞争条件。

异步任务可以在你开始收听事件之前完成,但这并不重要。任务的完成会创建一个事件,并且该事件将不会被处理,直到函数(或代码块)结束并且控件返回到浏览器。

答案 1 :(得分:1)

@Guffa是对的。但是,至少有两种情况你可以拥有竞争条件的外观

在未处理的ajax请求期间可能存在错误。考虑一些典型的XMLHttpRequest代码:

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);

如果readyState永远不是'4',则不会调用任何处理程序,也不会报告任何错误。您的成功处理程序永远不会被触发,因此您认为事件触发得太快而您没有注意到。


现在不常见,但也有一些情况下,浏览器可能会让您认为自己有竞争条件。 specification表示在错误条件下应该发生的事情,但并非总是这样。旧的/不符合的XMLHttpRequest实现在奇怪的网络条件下表现不佳。该规范的初始(约2006年)版本甚至没有解决网络级错误。

希望大多数浏览器现在都具有符合标准的实现,并且希望大多数框架应该正确处理错误条件。


对于异步调试有一个great article by Pearl Chen,如果你想深入挖掘,那么值得一读。

此外,有关ajax问题的更多信息:jQuery $.ajax, error handler doesn't work