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).

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

报告相同问题?

悬赏问题

  • ¥20 易康econgnition精度验证
  • ¥15 线程问题判断多次进入
  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致