为什么我的同步 jQuery AJAX 回调不起作用?

Why does my synchronous jQuery AJAX callback not work?

我想了解 jQuery AJAX 使用回调。所以我创建这个作为例子。

<?php 
  sleep($_POST['sleep']);
  echo 'sleep for '.$_POST['sleep'] .'sec';
?>
$(function () {
  var timer = [5,2,3,1,4];

  function sleep(timer) {
    $.ajax({
      url: 'ajax.php',
      data: { sleep: timer },
      type: 'post',
      success: function(d){
        console.log(d);
      },
      error: function(d){
        console.log(d);
      }
    });
  } 

  $('#ajax').click(function(){
    $.each(timer, function(i, e) {
      sleep(e);
    })
  });
});

结果:1,2,3,4,5 我想要的是:5,2,3,1,4(同步)

我知道我可以使用 async: false; 但这会挂断我的浏览器并且这也已被弃用。所以我想学习使用回调

进行同步

这是我的失败脚本:

<script src="http://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script lang="javascript" type="text/javascript">
$(function () {
  var timer = [5,2,3,1,4];

  $.each(timer, function(i, e) {
    sleep(e, function(d) {
      console.log(d);
    });
  });

  function sleep(sleepTimer, callback) {
    $.ajax({
      url: 'ajax.php',
      data: { sleep: sleepTimer },
      type: 'post',
      success: callback,
      error: function(data){
        console.log(data);
      }
    });
  } 
});
</script>

结果:1,2,3,4,5 改为 5,2,3,1,4

我做错了什么?

更新: 感谢那些提醒我这有多糟糕的人。但我现在别无选择。我的朋友需要我的帮助来编辑他的 drupal 页面。他只有管理员权限(不是系统管理员)。 我只能编辑视图,不能编辑控制器。为什么?

  1. 只有允许这样做的总部 IT 人员。
  2. 需要官僚主义和管理(用户要求、会议、质量保证 [安全测试 + 压力测试)。有趣的是,他们检查了所有的应用程序,而不仅仅是受我的脚本更改影响的页面
  3. 需要时间。非安全更改最快 1 个月

嘿..这听起来很有趣吧?即使您只添加 1 space,我们也需要他们(总部工作人员)所说的第 2 项要求。这个真实的故事。我知道这是因为我和他在同一个事工。

该脚本只是通过单击(一百个)下载单个文件,我的朋友要我添加复选框以允许他的团队批量下载。我可以添加复选框,并按顺序下载它们(这就是我尝试使用同步 ajax 所做的)。但是因为这会挂断他们的浏览器,所以我需要正确的方法来做到这一点。

我在这里有 2 个选择:使用 phantomjs(中等)或同步 ajax(简单)

TL;DR:因为它是异步而不是同步

您看到的行为对于正常的 异步 调用是完全正确的,结果的顺序无法保证并且可以是任何顺序。这是触发多个 AJAX 请求的最佳方式,假设调用之间没有依赖关系。

尽管出于某种原因你想同步执行此操作。

您需要更改代码,以便一次只发送一个请求,等待第一个请求完成后再发送第二个,依此类推。

您可以通过递归调用睡眠、删除(并使用)timers 中的第一个值来实现。

$(function () {
    var timer = [5,2,3,1,4];

    function sleep(timers){

        // check that timers is not empty first.
        if (timers == null || timers.length == 0)
            // if it is, we're done
            return;


        // remove the first value from timers
        var timer = timers.shift();

        $.ajax({
            url: 'ajax.php',
            data: {
                sleep: time
            },
            type: 'post',
            complete: function (jqXHR, textStatus) {
                // complete will get called on either success or error
                console.log(jqXHR);
                //recursively call sleep, first time through timers will be [2,3,1,4]
                sleep(timers);
            }
        });
    }

    $('#ajax').click(function(){
        // send the array of values to sleep instead
        sleep(timer);
    });
});