dongxixian7803 2013-08-01 10:44
浏览 17
已采纳

简单的JSONP和PHP示例不起作用

Been trying to create a simple JSONP call but it doesn't always work and I dunno why. Here's the code:

server-side (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;
    }
?>

client-side (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>

This code works and displays "It works!" in my

block.

  • Why isn't it working when I dont use {'callback': 'process'} and put ?callback=process straight into the $.getJSON() URL?

  • Why isn't it working if I use <script src="http://server/server.php?callback=process"></script> instead of the $.getJSON() call?

Both not-working cases actually return process("It works"); but this isn't executed, why?

Thanks

  • 写回答

1条回答 默认 最新

  • dongqiao2077 2013-08-01 11:34
    关注

    The are two different issues here, with different answers


    The reason it doesn't work when you use $.getJSON() and put the name of the callback literally in the URL is because of the way in which jQuery works.

    Firstly lets look at how jQuery detects that your $.getJSON() call is expecting JSONP if you don't pass any options that indicate it explicitly in the settings object - it uses this regular expression:

    /(=)\?(?=&|$)|\?\?/
    

    This looks explicitly for either =? in the query string or a query string consisting of nothing but a single ? - in essence, the question mark is required for detecting that the URL will return JSONP.

    Without it, jQuery makes an Ajax request using XHR and the correct data is returned by the server. What happens next depends on the Same Origin Policy. If, like the code you show, the server indicates via Access-Control-* headers that the request is allowed, the data will be accessible just liek it would be with an Ajax request to the client's origin server. If these headers are not present, the data returned will not be accessible to the client code.

    But, crucially, because it just makes a standard Ajax request and does not add a <script> element to the DOM, it means that the response text is never evaluated as Javascript code - the crucial last-step in the JSONP mechanism.


    The second version is a little trickier to answer and know that the answer is correct with the information provided, but with the HTML layout you show above I'm reasonably confident this is the reason: Your HTML elements are defined in the wrong order.

    When processing the DOM on page load, processing halts at every <script> element while the associated Javascript is synchronously loaded and processed. This is to ensure that all Javascript is executed in the intended order, and that any calls to things which directly modify the DOM in a location specific way - such as document.write() (which you should never use, in case you don't know) - are honoured correctly.

    The upshot of this is that if you placed the <script> element in the DOM before the <p id="result"> tag, the result tag doesn't actually exist at the point where the process() function is called. And because you used a jQuery selector instead of document.getElementById(), it swallows the error that would have resulted if you had tried to modify it directly.

    This is the reason that many Javascript developers (including myself) will now tell you that you should place your <script> tags as the very last elements in the <body>, as it gives a perceived performance improvement - even though in reality it takes exactly the same amount of network time to load and process all the page resources, it allows the browser to render the page quicker. Doing this also negates the need to use things like $(document).ready()/DOMContentLoaded events to delay execution (which, incidentally, would also solve this problem, but in a slightly messier way).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题