首页 > 解决方案 > Ajax 从不启动成功:使用 xhrFields 时

问题描述

我无法success在我的 ajax 请求中触发调用。我知道通信工作正常,但是我PHP脚本中的最后一个调用return json_encode($array);将触发,就好像它是 onprogress 对象的一部分一样。我想“中断” onprogress 调用并return json_encode在 PHP 脚本终止时通过发送的最后一个数据运行成功函数......

这是我的 AJAX 调用:

$( document ).ready(function(e) {
    var jsonResponse = '', lastResponseLen = false;   
    $("#btn_search").click(function(e){
      var firstname = document.getElementById('firstname').value;
      var lastname = document.getElementById('lastname').value;
        $.ajax({
          type: "POST",
          url: 'search.php',
          data: $('#search_fields').serialize(),
          dataType: "json",
          xhrFields: {
                onprogress: function(e) {
                    var thisResponse, response = e.currentTarget.response;
                    if(lastResponseLen === false) {
                        thisResponse = response;
                        lastResponseLen = response.length;
                    } else {
                        thisResponse = response.substring(lastResponseLen);
                        lastResponseLen = response.length;
                    }

                    jsonResponse = JSON.parse(thisResponse);
                    document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
                }
            },
            success: function(data) {
                console.log('done!');
                document.getElementById('progress').innerHTML = 'Complete!';
                document.getElementById('results').innerHTML = data;
            }
        });
        e.preventDefault();
    });
});

这是基本的 PHP 服务器脚本:

<?php
function progress_msg($progress, $message){
  echo json_encode(array('progress' => $progress, 'msg' => $message));
  flush();
  ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count < 100){
     progress_message($count, "working....");
     $count += 10;
     sleep(2);
}
return json_encode($array);
?>

标签: phpjqueryajax

解决方案


我让你的代码工作,有2个错误。首先,在你的while循环中,你的函数名不正确,试试这个:

progress_msg($count, "working... ." . $count . "%");

其次,最后一行什么也没输出,所以从技术上讲,你不会得到“成功”的 json 返回。更改服务器脚本的最后一行:

return json_encode($array);

到:

echo json_encode($array);

更新:带有hacky解决方案的完整工作代码:

阿贾克斯:

$( document ).ready(function(e) {
    var jsonResponse = '', lastResponseLen = false;   
    $("#btn_search").click(function(e){
      var firstname = document.getElementById('firstname').value;
      var lastname = document.getElementById('lastname').value;
        $.ajax({
          type: "POST",
          url: 'search.php',
          data: $('#search_fields').serialize(),
          xhrFields: {
                onprogress: function(e) {
                    var thisResponse, response = e.currentTarget.response;
                    if(lastResponseLen === false) {
                        thisResponse = response;
                        lastResponseLen = response.length;
                    } else {
                        thisResponse = response.substring(lastResponseLen);
                        lastResponseLen = response.length;
                    }

                    jsonResponse = JSON.parse(thisResponse);
                    document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
                }
            },
            success: function(data) {
                console.log('done!');
                dataObjects = data.split("{");
                finalResult = "{" + dataObjects[dataObjects.length - 1];
                jsonResponse = JSON.parse(finalResult);
                document.getElementById('progress').innerHTML = 'Complete!';
                document.getElementById('results').innerHTML = jsonResponse.msg;
            }
        });
        e.preventDefault();
    });

搜索.php:

<?php
function progress_msg($progress, $message){
  echo json_encode(array('progress' => $progress, 'msg' => $message));
  flush();
  ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count <= 100){
     progress_msg($count, "working... " . $count . "%");
     $count += 10;
     sleep(1);
}
ob_flush();
flush();
ob_end_clean();
echo json_encode($array);
?>

ajax 调用的“成功”方法的问题在于它无法将返回的数据解释为 JSON,因为完整的返回是:

{"progress":0,"msg":"working... 0%"}{"progress":10,"msg":"working... 10%"}{"progress":20,"msg":"working... 20%"}{"progress":30,"msg":"working... 30%"}{"progress":40,"msg":"working... 40%"}{"progress":50,"msg":"working... 50%"}{"progress":60,"msg":"working... 60%"}{"progress":70,"msg":"working... 70%"}{"progress":80,"msg":"working... 80%"}{"progress":90,"msg":"working... 90%"}{"progress":100,"msg":"working... 100%"}{"msg":"hello world"}

这不是一个有效的 JSON 对象,而是一个接一个地多重 JSON 对象。

我尝试使用 删除所有以前的输出ob_end_clean();,但由于某种原因我无法弄清楚,它在我的设置中不起作用。因此,相反,我想出的 hacky 解决方案是不将返回视为 JSON(通过dataType从 AJAX 调用中删除参数),并简单地将最终的 Json 元素与字符串操作分开......

必须有一个更简单的解决方案,但是如果不使用第三方 jQuery 库来支持 XHR 和 Ajax,我找不到任何解决方案。


推荐阅读