我正在寻找关于以下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?
});
如果答案得到实际语言规范(或其他权威来源)的支持,那就更好了!
答案 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。