一直试图创建一个简单的JSONP调用,但它并不总是有效,我不知道为什么.这是代码:
服务器端(http://server/server.php):
<?php
$res = json_encode("It works!");
if(isset($_GET['callback']) === TRUE) {
header('Content-Type: text/javascript;');
header('Access-Control-Allow-Origin: http://client');
header('Access-Control-Max-Age: 3628800');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
echo $_GET['callback']."(".$res.");";
} else {
echo $res;
}
?>
客户端(http://client/client.html):
<html>
<head><title>JSONP</title></head>
<body>
<h1>JSONP Experiment</h1>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
function process(data) {
$('#result').text(data);
}
$.getJSON(
'http://server/server.php?callback=?',
{'callback': 'process'}
);
</script>
<p id="result"></p>
</body>
</html>
此代码工作并显示“它工作!”在我的街区.
>当我不使用{‘callback’:’process’}并将?callback = process直接放入$.getJSON()URL时,为什么它不工作?
>如果我使用< script src =“http://server/server.php?callback = process”>< / script> ;,为什么它不起作用?而不是$.getJSON()调用?
两个非工作案例实际上都返回了流程(“它有效”);但是这没有被执行,为什么?
谢谢
解决方法:
这里有两个不同的问题,答案不同
当你使用$.getJSON()并将回调的名字直接放在URL中时它不起作用的原因是因为jQuery的工作方式.
首先让我们看看如果你没有传递任何在设置对象中明确指出它的选项,jQuery会检测到你的$.getJSON()调用是否期望JSONP – 它uses这个正则表达式:
/(=)\?(?=&|$)|\?\?/
这显然是为了?在查询字符串或查询字符串中只包含一个? – 实质上,问号是检测URL将返回JSONP所必需的.
没有它,jQuery使用XHR发出Ajax请求,服务器返回正确的数据.接下来会发生什么取决于同源策略.如果像您显示的代码一样,服务器通过Access-Control- *标头指示允许该请求,那么数据将是可访问的,只是对客户端的源服务器发出Ajax请求.如果这些标头不存在,则客户端代码将无法访问返回的数据.
但是,至关重要的是,因为它只是生成标准的Ajax请求而不添加< script> DOM的元素,这意味着响应文本永远不会被评估为Javascript代码 – 这是JSONP机制中至关重要的最后一步.
第二个版本回答起来有点棘手,并且知道所提供的信息答案是正确的,但是上面显示的HTML布局我有理由相信这是原因:您的HTML元素定义错误.
在页面加载时处理DOM时,处理在每个< script>处停止.元素,同时加载和处理关联的Javascript.这是为了确保所有Javascript按预期的顺序执行,并确保以特定位置的方式直接修改DOM的任何东西 – 例如document.write()(如果你不这样做,你应该永远不会使用它)知道) – 得到正确的尊重.
这样做的结果是,如果您放置< script> < p id =“result”>之前的DOM中的元素tag,结果标记实际上并不存在于调用process()函数的位置.并且因为您使用了jQuery选择器而不是document.getElementById(),所以如果您尝试直接修改它,则会吞下可能导致的错误.
这就是许多Javascript开发人员(包括我自己)现在会告诉您应该放置< script>的原因.标签作为< body>中的最后一个元素,因为它提供了感知的性能改进 – 即使实际上它需要完全相同的网络时间来加载和处理所有页面资源,它允许浏览器呈现页面更快.这样做也消除了使用诸如$(document).ready()/ DOMContentLoaded事件之类的事情来延迟执行的需要(顺便说一下,这也会解决这个问题,但是稍微有些麻烦).