Ajax请求成功但responseText为空,含代码求排查技术提示
点击List Books (XML)按钮时,通过Prototype.js的Ajax.Request向books.php发送选中的分类参数,请求进入onSuccess回调但弹出的ajax.responseText是空内容,请求已确认到达后端,求排查方向。
HTML代码片段
<label><input type="radio" name="category" value="children" checked="checked"/> Children</label> <label><input type="radio" name="category" value="computers" /> Computers</label> <label><input type="radio" name="category" value="cooking" /> Cooking</label> <label><input type="radio" name="category" value="finance" /> Finance</label> <button id="b_xml">List Books (XML)</button> <button id="b_json">List Books (JSON)</button>
JavaScript代码(基于Prototype.js)
window.onload = function() { $("b_xml").onclick=function(){ new Ajax.Request("books.php", { method:"GET", parameters: {category:getCheckedRadio(document.getElementsByName("category"))}, onSuccess: showBooks_XML, onFailure: ajaxFailed }) } $("b_json").onclick=function(){ //construct a Prototype Ajax.request object }; }; function getCheckedRadio(radio_button){ for (var i = 0; i < radio_button.length; i++) { if(radio_button[i].checked){ return radio_button[i].value; } } return undefined; } function showBooks_XML(ajax) { alert(ajax.responseText); } function showBooks_JSON(ajax) { alert(ajax.responseText); } function ajaxFailed(ajax, exception) { var errorMessage = "Error making Ajax request:\n\n"; if (exception) { errorMessage += "Exception: " + exception.message; } else { errorMessage += "Server status:\n" + ajax.status + " " + ajax.statusText + "\n\nServer response text:\n" + ajax.responseText; } alert(errorMessage); }
PHP代码
<?php $BOOKS_FILE = "books.txt"; function filter_chars($str) { return preg_replace("/[^A-Za-z0-9_]*/", "", $str); } if (!isset($_SERVER["REQUEST_METHOD"]) || $_SERVER["REQUEST_METHOD"] != "GET") { header("HTTP/1.1 400 Invalid Request"); die("ERROR 400: Invalid request - This service accepts only GET requests."); } $category = ""; $delay = 0; if (isset($_REQUEST["category"])) { $category = filter_chars($_REQUEST["category"]); } if (isset($_REQUEST["delay"])) { $delay = max(0, min(60, (int) filter_chars($_REQUEST["delay"]))); } if ($delay > 0) { sleep($delay); } if (!file_exists($BOOKS_FILE)) { header("HTTP/1.1 500 Server Error"); die("ERROR 500: Server error - Unable to read input file: $BOOKS_FILE"); } header("Content-type: application/xml"); print "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "; print "<books> "; $lines = file($BOOKS_FILE); for ($i = 0; $i < count($lines); $i++) { list($title, $author, $book_category, $year, $price) = explode("|", trim($lines[$i])); if ($book_category == $category) { print "\t<book category=\"$category\"> "; print "\t\t<title>$ti tle</title> "; print "\t\t<author>$author</author> "; print "\t\t<year>$year</year> "; print "\t\t<price>$price</price> "; print "\t</book> "; } } print "</books>"; ?>
books.txt内容
Freakonomics|Steven Levitt|finance|2006|18.00 Harry Potter and the Sorceror's Stone|J.K. Rowling|children|1998|19.99 Breakfast for Dinner|Amanda Camp|cooking|2009|22.00 Web Programming Step-by-Step|Marty Stepp and Jessica Miller|computers|2009|999.99 Building Java Programs|Stuart Reges and Marty Stepp|computers|2007|90.00 Core Java, 8th edition|Cay Horstmann|computers|2007|35.00 Personal Finance for Dummies|Eric Tyson|finance|2006|14.95 21 Burgers for the 21st Century|Stuart Reges|cooking|2010|75.00 The Four Food Groups of Chocolate|Victoria Kirst|cooking|2005|30.00 Go, Dog, Go!|P.D. Eastman|children|1961|8.99
先给你几个优先级最高的排查方向,一步步来:
修正PHP的变量拼写错误
你在输出<title>标签时写了$ti tle(中间多了空格),这会直接导致PHP解析错误。虽然设置了XML的Content-Type,但这种语法错误可能会让输出异常中断,最终返回空内容。先把这个改成$title再说,这大概率是核心问题。直接测试PHP接口
跳过JS,直接在浏览器地址栏输入books.php?category=children,看看返回的XML是什么。如果直接访问也为空,那问题肯定在PHP端;如果直接访问有正常内容,再回头查JS的参数传递。验证后端是否正确接收分类参数
在PHP代码的$category赋值后,加一行var_dump($category);,然后访问接口,看看输出的分类值是否和预期一致。比如选了children,后端拿到的是不是"children"?如果filter_chars函数把参数过滤成空了,那后续的书籍匹配自然不会有结果。检查文件读取权限和路径
虽然代码里判断了file_exists,但文件存在不代表PHP有读取权限。可以在file_exists后面加个is_readable($BOOKS_FILE)的检查,如果没权限就返回错误提示。另外确认books.txt和books.php在同一目录,或者用绝对路径指定文件位置(比如/var/www/html/books.txt)。确认JS参数传递正确
在JS的$("b_xml").onclick函数里,先打印getCheckedRadio(document.getElementsByName("category"))的返回值,看看传给后端的参数是不是正确的分类值,避免参数为空或者错误导致后端没匹配到书籍。查看Prototype的响应细节
在showBooks_XML函数里,除了responseText,再打印ajax.status和ajax.responseXML,确认状态码是200,且响应确实被正确解析。有时候XML类型的响应会优先存到responseXML里,但responseText也应该有内容。
内容的提问来源于stack exchange,提问作者권태형

