【问题标题】:How can I call ajax synchronously without my web page freezing如何在不冻结网页的情况下同步调用 ajax
【发布时间】:2014-10-08 23:24:11
【问题描述】:

我有一些 javascript 可以触发大约 100 次对 php 脚本的调用。 php 脚本占用大量内存并需要几秒钟才能完成,然后返回通过或失败的 json 响应。

我不希望 ajax 调用是异步的,因为服务器会停止运行 100 个自身实例,因此我尝试使用同步,唯一的问题是它在调用脚本时冻结网页一次。

如何一次触发一个 ajax 调用而不冻结我所在的页面?

var a = [];
    a[0] = 'test';
    a[1] = 'hello';
    a[2] = 'another';

$(document).ready(function(){ 
  $.each(a, function(k,v) {
$.ajax({
  url:'/this-script-takes-a-few-seconds-to-complete.php',
  async:false,
  data: {foo: v},
  success: function(data){      
    console.log(data);  
  }
});
  });
});

【问题讨论】:

  • ...你到底在做什么需要 100 个 ajax 请求?

标签: jquery ajax webpage freeze


【解决方案1】:

您可以放入一个执行下一次调用的函数,并从您的 success 处理程序中调用它,如下所示:

$(function(){ 
  var i = 0;
  function nextCall() {
    if(i == a.length) return; //last call was last item in the array
    $.ajax({
      url:'/this-script-takes-a-few-seconds-to-complete.php',
      data: { foo: a[i++] },
      success: function(data){      
        console.log(data);  
        nextCall();
      }
    });
  }
  nextCall();
});

虽然...更好的方法是不进行 100 次调用,除非这是某种测试套件,否则我会重新审视整个方法。

【讨论】:

  • 注意:如果您从 ajax 回调的执行上下文中触发 Ajax 请求,IE6 会阻塞。将 nextCall() 调用包装在 setTimeout() 中以避免该问题(如果您的目标是 IE6 兼容性)。
  • @Nick:我需要 100 多个电话。有什么建议的解决方案吗?
  • 这件事救了我的命,但问题是我发现它很晚
【解决方案2】:

如果您不希望您的调用是异步的,那么浏览器将无法更新将冻结的 UI。为什么不能让它异步?而不是一次完成所有 100 个,只需等待一个完成,然后调用下一个。

【讨论】:

  • 最好的方法是什么?
  • 设置 i = 0;然后用 a[i] 作为参数调用,然后当它完成时(使用成功函数),增加 i 并再次调用它。当 i == a.length 时,你就完成了。
【解决方案3】:

你需要重构这个东西。 100 个 ajax 请求太疯狂了,而且它们都是同步的。

我建议你重构你的应用,这样你就可以解析所有数据并在一个异步 go 或几个异步请求中发送它,而不是 100 个。

如果您需要 100 个,请创建某种队列并按顺序异步处理它们。

【讨论】:

  • 我假设他无法在一个电话中完成所有操作,因为他想在每个请求之间更新用户界面。但是,如果他能在一个请求中完成所有工作,那就太好了。
【解决方案4】:

问题在于 Ajax... 代表“异步 JavaScript 和 XML”...

试图同步执行 Ajax 违背了使用 Ajax 的初衷。

尝试使用线程池并异步运行。

【讨论】:

    【解决方案5】:

    编辑 - 正确答案

    大多数浏览器会限制对单个服务器的 HTTP 请求数量,大概是为了防止出现与您试图防止的情况完全相同的情况(服务器过载)。我不确定现代浏览器的实际数字是多少,但我认为它比我在 2005 年在 Firefox 中观察到的旧“2”还要多。

    一些资源:

    旧答案

    此脚本将每 2 秒调用一次同步 $.ajax,每次将数据移出数组 a。在每个请求实际执行期间,UI 仍将锁定,但允许它在调用之间自我更新。我认为,这是完全同步和完全异步之间的一个很好的折衷。

    请注意,此脚本具有破坏性 - a 完成后将为空。如果您需要a 的内容,那么您可能需要创建一个副本。

    a = [
        'test',
        'hello',
        'another'
    ];
    
    $(function() {
        var send = function() {
            $.ajax({
                url: '/this-script-takes-a-few-seconds-to-complete.php',
                async: false,
                data: {foo: a.shift()},
                success: function(data) {
                    console.log(data)
                }
            });
    
            if (!a.length)
            {
                clearInterval(timer);
            }
        }
    
        var timer = setInterval(send, 2000);
    });
    

    【讨论】:

      【解决方案6】:

      我有类似的问题,我需要同步调用并且 IE 冻结了。简而言之,我想出了这种方法。

      1. 我没有使用同步调用,而是使用 async:true。
      2. 在 complete:function 中递归调用下一个 ajax 请求。

      它允许我异步调用同步调用,所以我在前一个调用之后调用。

      【讨论】:

      • 此解决方案已在此问题的已接受答案中提供。请在提供您自己的解决方案之前阅读现有解决方案,因为这样可以避免重复,而是向问题添加其他信息。对于非常古老的问题尤其如此,因为社区可能已经多次审查了问答,因此很少有任何东西可以改善它。哦,顺便说一句,欢迎来到 StackOverflow!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 2021-12-19
      • 2011-12-27
      相关资源
      最近更新 更多