js jsonp

json和jsonp的關係

  • JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。它基於 ECMAScript (w3c制定的js規範)的一個子集,採用徹底獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON 成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提高網絡傳輸效率。
  • JSONP(JSON with Padding)是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。

json和jsonp縮寫只相差一個字母,可是二者卻徹底不一樣。前者是一種數據的表達方式,後者則是網絡請求的一種解決方案。javascript

同源策略

使用ajax發送網絡請求有一個條件,那就是同源策略php

同源策略要求:java

  1. 協議類型相同 -> httphttpsftp等等
  2. 主機地址相同 -> https://www.baidu.com/ 或者本身的主機ip地址
  3. 端口號相同 -> 808080等等

例如日常使用webstorm進行調試的時候,webstorm會開一個本地服務器http://localhost:63342/xxxx,可是若是你使用ajax去訪問https://www.baidu.com/之類的服務器你是沒法拿到數據的。實際上瀏覽器已經拿到數據,可是作了一層隔離,不給你數據。node

jsonp原理

在說原理以前首先要了解兩個關於<script>的特色web

  1. <script>標籤可使用cdn加速(根據瀏覽器所在網絡地區,從最近的服務器下載js腳本,通常下載框架和庫),那麼cdn的服務器毫無疑問是不一樣源的。因此,<script>標籤能夠跨域訪問別的服務器
  2. <script>標籤是經過src節點屬性獲取js代碼的,而且獲取到的代碼能夠直接執行

在瞭解了上面的2個<script>的特色以後大概都能猜出來,jsonp就是使用<script>以上兩個特色來實現的,具體的實現方式有2種。ajax

  • 方式一編程

    1. 建立一個函數(名字隨機生成,避免屢次請求被覆蓋),而且接收一個參數(服務器返回的數據)。
    2. 利用<script>標籤發送請求,拼接上callback=方法名參數。
    3. 後端要求接收這個callback參數,拿到方法名後在方法名後拼接(),而且傳入返回的數據

這種方式對於php來講就是字符串拼接,可是傳回來的時候則是被js解析成調用對應的方法了。json

// php
$res = file_get_contents($url);
$func = $_GET[callback];

echo callback.'('.$res.')';
  • 方式二後端

    1. 使用php或者nodejs去訪問須要跨域的請求
    2. 用ajax訪問這個php或者nodejs腳本

jsonp不管如何都要後端支持(要麼是本身的後端寫的php,要麼是別人接口支持jsonp跨域的回調方法),不然沒法使用。api

 方式一示例

// 1. 建立一個script標籤
var script = document.createElement('script');

// 2. 隨機生成一個方法
// 用時間戳做爲種子,這樣隨機生成的方法名絕對沒有重複的。
var funcName = 'jsonpFunc' + Math.floor(new Date().getTime() * Math.random());
window[funcName] = function (json) {
    console.log(json);

    // 把請求完的標籤從文檔中移除
    document.head.removeChild(script);
};

// 3. 拼接請求地址,加上回調
script.src = 'http://api.douban.com/v2/movie/in_theaters?callback=' + funcName;

// 4. 把script標籤放到文檔中,就會發送請求
document.head.appendChild(script);

封裝一下:

window.myJsonp = function (opt) {

    // 簡單的容錯
    if (!opt || !opt.url) return;
    opt.callback = opt.callback || 'callback';
    opt.params = opt.params || {};
    opt.callback = opt.callback || function () {};

    // 1. 建立一個script標籤
    var script = document.createElement('script');

    // 2. 隨機生成一個方法
    var funcName = 'jsonpFunc' + Math.floor(new Date().getTime() * Math.random());
    window[funcName] = function (json) {

        // 5. 把請求完的標籤從文檔中移除
        document.head.removeChild(script);
        // 6. 刪除添加到window的方法名稱,避免污染
        delete window[funcName];

        // 7. 把獲取到的數據經過回調的方式傳出去
        opt.callback(json);
    };

    // 3. 拼接請求地址,加上回調(參數拼接和get請求一致)
    var params = '';
    for (var key in opt.params) {
        params += key + '=' + opt.params[key] + '&';
    }
    script.src = opt.url + '?' + params + 'callback=' + funcName;

    // 4. 把script標籤放到文檔中,就會發送請求
    document.head.appendChild(script);
};


// 使用
myJsonp({
    url: 'http://api.douban.com/v2/movie/in_theaters',
    callback: function (json) {
        console.log(json);
    }
});

方式二

待續。。。

相關文章
相關標籤/搜索