[javascript] 什麼是JSONP?



2 Answers

JSONP是一個簡單的技巧來克服XMLHttpRequest相同的域策略。 (如你所知,你不能將AJAX(XMLHttpRequest)請求發送到不同的域。)

因此,我們不必使用XMLHttpRequest,而是使用腳本 HTML標籤,這是您通常用來加載js文件的腳本 ,以便js從另一個域中獲取數據。 聽起來怪怪的?

事情是 - 原來的腳本標籤可以以類似於XMLHttpRequest的方式使用! 看一下這個:

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';

加載數據後,您將看到如下所示的腳本段:

<script>
{['some string 1', 'some data', 'whatever data']}
</script>

然而,這有點不方便,因為我們必須從腳本標記中獲取這個數組。 所以JSONP創作者決定這會更好地工作(而且是):

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';

注意那邊的my_callback函數? 所以 - 當JSONP服務器收到你的請求並找到回調參數時 - 而不是返回普通的js數組,它會返回這個:

my_callback({['some string 1', 'some data', 'whatever data']});

看看利潤在哪裡:現在我們得到自動回調(my_callback),一旦我們獲得數據就會觸發它。
這就是所有關於JSONP的知識 :它是一個回調和腳本標籤。

注意:這些是JSONP用法的簡單示例,這些不是生產就緒腳本。

基本的JavaScript示例(使用JSONP的簡單Twitter推送)

<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>

基本的jQuery示例(使用JSONP的簡單Twitter推送)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>


JSONP代錶帶有Padding的JSON 。 (名字很差,因為它與大多數人認為的“填充”無關。)

Question

這個問題在這裡已經有了答案:

我了解JSON,但不了解JSONP。 關於JSON的Wikipedia文檔是(是)JSONP的最高搜索結果。 它說:

JSONP或“帶填充的JSON”是JSON擴展,其中前綴被指定為調用本身的輸入參數。

咦? 什麼呼叫? 這對我來說沒有任何意義。 JSON是一種數據格式。 沒有電話。

第二個搜索結果來自一位Remy ,他寫了關於JSONP的文章:

JSONP是腳本標記註入,將來自服務器的響應傳遞給用戶指定的函數。

我可以理解,但它仍然沒有任何意義。

那麼什麼是JSONP? 它為什麼被創建(它解決了什麼問題)? 為什麼我會使用它?

附錄 :我剛剛在Wikipedia 上為JSONP創建了一個新頁面 ; 它基於jvenema的回答,現在對JSONP有了一個清晰而全面的描述。




一個使用JSONP的簡單例子。

client.html

    <html>
    <head>
   </head>
     body>


    <input type="button" id="001" onclick=gO("getCompany") value="Company"  />
    <input type="button" id="002" onclick=gO("getPosition") value="Position"/>
    <h3>
    <div id="101">

    </div>
    </h3>

    <script type="text/javascript">

    var elem=document.getElementById("101");

    function gO(callback){

    script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'http://localhost/test/server.php?callback='+callback;
    elem.appendChild(script);
    elem.removeChild(script);


    }

    function getCompany(data){

    var message="The company you work for is "+data.company +"<img src='"+data.image+"'/   >";
    elem.innerHTML=message;
}

    function getPosition(data){
    var message="The position you are offered is "+data.position;
    elem.innerHTML=message;
    }
    </script>
    </body>
    </html>

server.php

  <?php

    $callback=$_GET["callback"];
    echo $callback;

    if($callback=='getCompany')
    $response="({\"company\":\"Google\",\"image\":\"xyz.jpg\"})";

    else
    $response="({\"position\":\"Development Intern\"})";
    echo $response;

    ?>    



因為您可以要求服務器為返回的JSON對象附加前綴。 例如

function_prefix(json_object);

以便瀏覽器將JSON字符串“內嵌”為表達式。 這個技巧使得服務器可以直接在客戶端瀏覽器中“注入”JavaScript代碼,並繞過“同源”限制。

換句話說,你可以進行跨域數據交換

通常, XMLHttpRequest不允許直接跨域數據交換(需要通過同一域中的服務器),而:

<script src="some_other_domain/some_data.js&prefix=function_prefix >`可以訪問來自不同於源的域的數據。

另外值得注意的是,即使服務器在嘗試這種“技巧”之前應該被視為“可信”,也可以包含對象格式等可能變化的副作用。 如果一個function_prefix (即一個合適的js函數)被用來接收JSON對象,那麼所述函數可以在接受/進一步處理返回的數據之前執行檢查。




Related