AJAX请求返回SyntaxError: Unexpected token '<'问题排查求助
我正在编写一个JavaScript函数,从GeoJSON文件中根据国家名称匹配对应的JSON对象并提取国家代码,再将该代码作为参数调用API获取国家信息并展示在模态框中。但出现错误SyntaxError: Unexpected token '<', "<?php,无法定位问题所在,怀疑该错误与countryInfo.php的AJAX调用有关。
相关代码
JavaScript代码
let code $('#innerSelect').on('change', async () => { //Handles changing the country select. await addCountryBorder($('#innerSelect').val()) /* Calls function that adds country border to map */ countryInfo($('#innerSelect').val()) const result = await $.ajax({ url: 'libs/php/getCoordsFromCountryName.php', type: 'GET', dataType: 'json', data: { countryName: $('#innerSelect').val() } }) if (result.status.name == 'ok') { const { lat, lng } = result.data[0].geometry map.panTo(new L.LatLng(lat, lng)) } }); /* Function responsible for adding border to a given country and grabbing country code*/ async function addCountryBorder (countryName) { const result = await $.ajax({ url: 'assets/geojson/countryBorders.geo.json', type: 'GET', dataType: 'json', data: {} }) const features = result.features const countryFeature = findFeatureFromName(countryName) if (!countryFeature) return if (border) map.removeLayer(border) border = new L.geoJSON(countryFeature.geometry, { style: { color: '#006600' } }).addTo(map) map.panTo(border.getBounds().getCenter()) map.fitBounds(border.getBounds()) console.log(countryFeature) } function countryInfo(countryName) { $.ajax({ url: "assets/geojson/countryBorders.geo.json", type: "GET", dataType: "json", data: { }, success: function(result) { let features = result["features"]; let countryFeature = findFeatureFromName(countryName); countryCode = JSON.stringify(countryFeature.properties.iso_a2) console.log(countryCode) $.ajax({ url: "assets/php/countryInfo.php", type: 'POST', dataType: 'json', data: { country: countryCode, }, success: function(result) { console.log(JSON.stringify(result)); if (result.status.name == "ok") { $('#continent').html(result['data'][0]['continentName']); $('#capital').html(result['data'][0]['capital']); $('#countryName').html(result['data'][0]['countryName']); $('#population').html(formattedPopulation); $('#currencyCode').html(result['data'][0]['currencyCode']); } }, error: function(jqXHR, textStatus, errorThrown) { console.log(errorThrown); } }); } }); }
PHP代码
<?php // remove for production ini_set('display_errors', 'On'); error_reporting(E_ALL); $executionStartTime = microtime(true); $url='http://api.geonames.org/countryInfoJSON?formatted=true&country=' . $_REQUEST['country'] . '&username=username&style=full'; $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_URL,$url); $result=curl_exec($ch); curl_close($ch); $decode = json_decode($result,true); $output['status']['code'] = "200"; $output['status']['name'] = "ok"; $output['status']['description'] = "success"; $output['status']['returnedIn'] = intval((microtime(true) - $executionStartTime) * 1000) . " ms"; $output['data'] = $decode['geonames']; header('Content-Type: application/json; charset=UTF-8'); echo json_encode($output); ?>
HTML代码
<!-- The Modal --> <div class="modal fade" id="myModal"> <div class="modal-dialog"> <div class="modal-content"> <!-- Modal Header --> <div class="modal-header"> <h4 class="modal-title">Information</h4> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <!-- Modal body --> <div class="modal-body"> <h6 id="countryName" class="modal-sub-header"></h6> <hr> <ul class="dem"> <li class="listItem">Capital City: <span class="test" id="capital"></span></li> <li class="listItem">Continent: <span class="test" id="continent"></span></li> <li class="listItem">Population: <span class="test" id="population"></span></li> <li class="listItem">Currency: <span class="test" id="currencyCode"></span></li> <li class="listItem">Area (km<sup>2</sup>): <span class="test" id="area"></span></li> </ul> </div> </div> </div> </div>
控制台错误信息
SyntaxError: Unexpected token '<', "<?php //"... is not valid JSON at parse (<anonymous>) at ajaxConvert (jquery-3.5.1.js:9260:19) at done (jquery-3.5.1.js:9736:15) at XMLHttpRequest.<anonymous> (jquery-3.5.1.js:10047:9)
错误分析与解决步骤
错误核心原因
这个错误说明AJAX请求没有拿到预期的JSON数据,反而拿到了PHP文件的源码(或带HTML标签的错误页面),导致JSON解析失败,常见触发点:
- 服务器未配置PHP解析:PHP文件被当作纯文本返回,而非执行后输出JSON
- 请求路径错误:
countryInfo.php的URL写错,服务器返回404 HTML页面 - PHP代码执行出错:PHP运行时输出了带HTML的错误信息,而非合法JSON
- 参数传递错误:JS传递的国家代码格式不对,导致PHP调用第三方API失败,进而输出异常内容
逐个排查解决
验证PHP文件能否正常执行
直接在浏览器地址栏输入http://你的域名/assets/php/countryInfo.php?country=CN,如果显示PHP源码,说明服务器没配置PHP环境(比如用了纯静态服务器),需要换成XAMPP/WAMP这类支持PHP的环境,或者调整服务器配置。检查AJAX请求路径
打开浏览器开发者工具的「网络」面板,查看countryInfo.php请求的状态码:- 若为404:说明路径写错,核对文件实际位置和AJAX里的
url是否一致 - 若为200但返回源码:回到第一步解决PHP解析问题
- 若为404:说明路径写错,核对文件实际位置和AJAX里的
修正国家代码传递逻辑
JS里用JSON.stringify(countryFeature.properties.iso_a2)会把代码变成带双引号的字符串(比如"CN"),传到PHP后拼接的API URL会变成country="CN",导致第三方API返回错误。改成直接传原始值:// 去掉JSON.stringify,直接取原始值 countryCode = countryFeature.properties.iso_a2优化PHP参数处理
PHP里用$_REQUEST不够严谨,POST请求直接用$_POST,同时对参数做URL编码避免拼接错误:// 替换原有的URL拼接代码 $country = urlencode($_POST['country']); $url="http://api.geonames.org/countryInfoJSON?formatted=true&country={$country}&username=你的实际用户名&style=full";注意:把代码里的
username=username换成你在GeoNames注册的真实用户名。排查PHP执行错误
在PHP文件里添加调试代码,查看curl请求是否成功:$result=curl_exec($ch); // 临时添加,查看curl返回的内容 var_dump($result); curl_close($ch);如果返回错误信息,根据提示修复(比如GeoNames用户名无效、API请求频率超限等)。
内容的提问来源于stack exchange,提问作者javascript_bewildered934

