JSONP解決跨域請求問題

頭像是我偶像發表於2017-07-16

一、何為跨域請求?

由於瀏覽器同源策略,不允許跨域請求資料,凡是傳送請求url的協議、域名、埠三者之間任意一與當前頁面地址不同即為跨域。具體可以檢視下錶:
image

二、JSONP的由來

1、一個眾所周知的問題,Ajax直接請求普通檔案存在跨域無許可權訪問的問題,甭管你是靜態頁面、動態網頁、web服務、WCF,只要是跨域請求,一律不準;

2、不過我們又發現,Web頁面上呼叫js檔案時則不受是否跨域的影響(不僅如此,我們還發現凡是擁有”src”這個屬性的標籤都擁有跨域的能力,比如script,img等標籤);

3、於是可以判斷,當前階段如果想通過純web端(ActiveX控制元件、服務端代理、屬於未來的HTML5之Websocket等方式不算)跨域訪問資料就只有一種可能,那就是在遠端伺服器上設法把資料裝進js格式的檔案裡,供客戶端呼叫和進一步處理;

  4、恰巧我們已經知道有一種叫做JSON的純字元資料格式可以簡潔的描述複雜資料,更妙的是JSON還被js原生支援,所以在客戶端幾乎可以隨心所欲的處理這種格式的資料;

  5、這樣子解決方案就呼之欲出了,web客戶端通過與呼叫指令碼一模一樣的方式,來呼叫跨域伺服器上動態生成的js格式檔案(一般以JSON為字尾),顯而易見,伺服器之所以要動態生成JSON檔案,目的就在於把客戶端需要的資料裝入進去。

  6、客戶端在對JSON檔案呼叫成功之後,也就獲得了自己所需的資料,剩下的就是按照自己需求進行處理和展現了,這種獲取遠端資料的方式看起來非常像AJAX,但其實並不一樣。

  7、為了便於客戶端使用資料,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP,該協議的一個要點就是允許使用者傳遞一個callback引數給服務端,然後服務端返回資料時會將這個callback引數作為函式名來包裹住JSON資料,這樣客戶端就可以隨意定製自己的函式來自動處理返回資料了。

  如果對於callback引數如何使用還有些模糊的話,我們後面會有具體的例項來講解。

三、JSONP的實現

可以使用jsonp解決跨域的問題,具體步驟:
1、在js中不能跨域請求資料,js可以跨域請求js片段。
2、可以把資料包裝成js片段。可以把資料使用js方法來包裝,形成一條方法的呼叫語句。
3、可以使用ajax請求js片段,當js判斷到達瀏覽器會被立即執行。
4、在瀏覽器端,先建立好回撥方法,在回撥方法中通過引數可以獲得請求的資料。
JSONP實現流程圖

前提準備:
1、需要把js的回撥方法先寫好。(此處為getDataService方法)

getDataService: function(a) {
        var b = [], c = this;
        $.each(a.data, function(a) {
            this.index = a, "l" == this.t && (this.i = c.FN_RefactorJSON(this.i, 7)), b.push(c.renderItem(this, a))
        });
        b.push('<div class="extra"><a {if pageConfig.isHome}clstag="homepage|keycount|home2013|0614a"{/if} href="http://www.jd.com/allSort.aspx">\u5168\u90e8\u5546\u54c1\u5206\u7c7b</a></div>'), this.OBJ.attr("load", "1").html(b.join("")), $.bigiframe(this.OBJ), this.FN_GetBrands();
        var d = this, e = this.OBJ.outerWidth(), f = this.OBJ.outerHeight();
        $("#_JD_ALLSORT").dropdown({delay: 0,onmouseleave: function() {
                $("#_JD_ALLSORT .item").removeClass("hover")
            }}, function(a) {
            var b, c, g = document.documentElement.scrollTop + document.body.scrollTop, h = $("#nav-2013").offset().top + 39;
            h >= g ? (c = a.hasClass("fore13") ? 3 : 3, g = c) : (b = a.offset().top, g = g > b - 5 ? b - h - 10 : Math.max(3, g - h));
            var i = a.find(".i-mc");
            if (i.css({top: g + "px"}), d.OBJ.find("iframe")) {
                var j = i.outerWidth() + e, k = i.outerHeight() > f ? i.outerHeight() : f;
                d.OBJ.find("iframe").css({width: j,height: k,top: g})
            }
        })
    }

2、做ajax請求時,需要把回撥方法的方法名傳遞給服務端。(傳遞一個callback引數)

URL_Serv: "http://localhost:8080/rest/category.json?callback=category.getDataService",//跨哉的情況下

3、服務端接收回撥方法名,把資料包裝好,響應給客戶端。
將json資料包裝成js。

category.getDataService({"data":[{"u":"products/1.html","n":"<a href='products/1.html'>圖書、音像、電子書刊</a>","i":[{"u":"products/2.html","n":"電子書刊","i":["products/3.html|電子書","products/4.html|網路原創","products/5.html|數字雜誌","products/6.html|多媒體圖書"]}]});

相關文章