并行异步jQuery-AJAX-Requests相互阻塞

时间:2013-11-20 12:56:19

标签: javascript jquery ajax asynchronous

我使用jQuery做一些异步后台数据获取。我偶然发现了这个问题,在第一个请求处理程序完成之前,对同一个URL的多个并行请求没有完成。

我创建了一个简单的例子来演示这个问题:

<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
<button id="js">Click me!</button>
<div>Request 1: <span id="resp1">-</span></div>
<div>Request 2: <span id="resp2">-</span></div>
<script type="text/javascript">
    $('#js').click(function() {
        $('#resp1, #resp2').html('...');
        $.ajax({
            url : 'http://stackoverflow.com',
            async : true,
            complete: function(request, textStatus) {
                $('#resp1').html('complete');
                alert('The second request is not completed, until you close this alert!'); 
            }
        });
        $.ajax({
            url : 'http://stackoverflow.com',               
            async : true,
            complete: function(request, textStatus) { 
                    $('#resp2').html('complete');
            }
        });
    });
</script>
</body>
</html>

单击按钮后,将生成两个并行的AJAX请求。第一个正常完成,但第二个没有,直到第一个的警报关闭。如果将第二个ajax请求移动到第一个ajax请求的完整事件处理程序中,问题仍然存在。

这是一个错误还是一个功能? 有解决方法吗?

修改

好的,我明白alert()会导致问题。但是我无法解释其他两件事。

  1. 当我将第二个ajax-call移动到第一个的完整处理程序(在alert()之前)并将第一个ajax-call更改为async:false时,它就可以了。警报()不应该导致同样的问题吗?

  2. 警报必须比Browsers JS-Thread阻止更多,因为如果我在另一个选项卡中打开AJAX-Request,它仍然无法加载,直到我关闭第一个选项卡中的alert-Box。 JS没有参与这里。奇怪。这可能是另一个问题吗?

2 个答案:

答案 0 :(得分:1)

这是预期的。 alert()阻止执行直到它关闭。

执行这些行时会发生什么

$('#resp1').html('complete');
alert('The second request is not completed, until you close this

是第一行触发ajax请求,但是下一行的执行如此之快,以至于ajax请求没有时间完成。一旦模态警报对话框初始化,执行就会暂停。 ajax请求可能处于仍然检索响应的状态,可能正在处理它,但它会暂停,直到警报关闭。

答案 1 :(得分:1)

完成与否的整个前提纯粹基于执行异步请求之间的竞争条件,因为第一个异步请求的回调中的alert()。如果第二个请求比第一个请求快(足够快以弥补它在第一个请求之后启动的事实)那么你就不会看到你关注的是什么

关于#1不,这不会是相同的,因为当您在警报之前进行ajax调用并且使用async : false时,ajax请求将在完成之前完成(到警报)。换句话说,您在此处完全同步,因为您处于唯一异步事件的回调中。顺便说一下,不要使用async: false

如前所述,alert()正在阻止执行。

仅供参考,您可以使用它来制作小提琴并使用计时 - 请注意在请求的delay对象中使用data。请注意,在此示例中,由于我设置的时间,两者是如何完成的,但如果您将其反转,则在alert()被清除之前它将无法完成。

最后不要使用alert() !!

fiddle