2011-03-21 47 views
1

我有以下代码,我想异步运行,但日志显示它们正在同步运行。JQuery AJAX请求表现为同步不明原因

$(".widget").each(function() { 
    // snip - url, def, and tempParams defined here 
$.ajax({ 
    url: url, 
    dataType: "jsonp", 
    type: "POST", 
    data: {params: tempParams}, 
    success: function(data) { 
     var st = new Date().getTime(); 
     console.error("Start " + def.name + " @" + st); 
     doSomething(data); 
     var et = new Date().getTime(); 
     console.error("End " + def.name + " @" + et); 
     console.error("Duration " + def.name + " " + (et-st) + " ms."); 
    } 
}); 

控制台输出清楚地显示了成功职能,以便执行,而不是异步:

Start f1 @1300738891705 
End f1 @1300738891744 
Duration f1 39 ms. 
Start f2 @1300738892746 
End f2 @1300738893280 
Duration f2 534 ms. 
Start f3 @1300738893282 
End f3 @1300738893303 
Duration f3 21 ms. 
Start f4 @1300738893305 
End f4 @1300738893306 
Duration f4 1 ms. 
Start f5 @1300738893484 
End f5 @1300738895609 
Duration f5 2125 ms. 

的思考?我觉得这一定是我忽略的事情。

回答

1

我认为你们都混淆了这两个术语。就AJAX而言是异步的,因此JQuery意味着HTTP请求消息将被发送到网络服务器,而不会在客户端造成任何延迟。这些请求很可能会顺序发送到服务器,但我不认为这是有保证的。我认为你在考虑线程...

同步调用可能导致客户端延迟,而浏览器的JavaScript解释器正在等待AJAX​​响应。

想一想一个简单的例子,可以说你有一个AJAX调用来获取美国州的税率。如果它是一个同步调用,那么结账工具将停止计算,并且任何与Javascript的用户交互都不会产生响应,直到收到AJAX响应(与税率)。

在上面的异步情况下,您可以定义一个回调函数,一旦收到AJAX响应,它将继续计算最终结帐价格。

+0

我知道这是愚蠢的。我在ajax调用之外添加了调试代码(就像我应该做的那样),它们确实是异步执行的。我正在想象他们会在他们自己的线程中执行,这导致了我对错误的理解。感谢您清理东西! – 2011-03-21 21:01:07

1

调试输出全部来自success函数,该函数在请求完成并且结果到达后被调用。即使这些请求是异步完成的,结果也会在他们进来时被一个接一个地处理。

在您的示例中,您可能会启动五个请求,这些请求在后台同步运行(异步)。第一个结果进入后,浏览器会调用第一个函数success,该函数为您提供f1函数的调试输出。完成此处理后,浏览器会查看是否同时完成了更多请求,并继续为这些请求调用success函数。

ajax请求的结果可能与您请求的顺序相同,以便您按顺序获取日志消息。但是也有可能一个请求需要更长的时间,例如在f3之前得到的日志输出为f4,因为结果要早得多。

+0

你是完全正确的 - 我只是在ajax调用之前添加了控制台输出,他们确实以不同于发送的顺序返回,所以它们实际上表现为异步。我的问题似乎是,锁定某些作业成功的UI将产生请求阻止的印象。 – 2011-03-21 20:59:33

1

试试这个...

var st = new Date().getTime(); 
console.error("Start " + def.name + " @" + st); 
$.ajax({ 
    url: url, 
    dataType: "jsonp", 
    type: "POST", 
    data: {params: tempParams}, 
    success: function(data) { 
     doSomething(data); 
     var et = new Date().getTime(); 
     console.error("End " + def.name + " @" + et); 
     console.error("Duration " + def.name + " " + (et-st) + " ms."); 
    } 
}); 
0

我相信,通过观察MGM并行执行的实际问题一直被忽视 becuse他进行时间记录为“成功”功能的一部分。 他对asyn进行了一般性解释。请求的性质作为答案,然而, 这里有一个问题。

看看下面的代码片段:

$(function() { 
     $(".dd").each(function() { 
      var obj = $(this); 
      $.get("test.txt", function(data) { 
       obj.html(data); 
      }); 
     }); 
    }); 

它加载一个文件(异步我所期望的),并将其显示(同步的课程)。

但是,在首次加载页面和刷新页面时,代码的执行方式不同。 我在Windows上使用Firefox 4.0中的Firebug Net面板监视对服务器的请求。 在第一页加载时(或使用Ctrl-F5刷新时),我可以在网络面板 上看到多个请求“test.txt”同时启动,网络活动主要覆盖。

该零件按预期工作。结果可能会在浏览器中逐一处理, ,但对服务器的请求是并行执行的。

(图像:初始负荷) (http://i.stack.imgur.com/nSFld.gif)

它是完全地不同故事whne用户按下F5刷新页面。突然间的并行性消失了。
同样的网页一个接一个加载“test.txt”。

(图像:后续刷新) (http://i.stack.imgur.com/7cYfM.gif) 如果我替换数据显示它变得更加清晰(obj.html(数据))用简单警报:警报(数据); 在初始页面加载时,我同时在屏幕上显示多条警报消息。 后续刷新(F5)清楚地表明,虽然屏幕上有一条警报消息,但没有其他 下载被执行(我可以删除文件以查看“$ .get”失败)。

所以实际上$ .get不执行异步。调用服务器。

关于为什么会发生这种情况的任何想法?

P.S. 对不起系统不允许我发布图片。