jsonp 演示實例 —— 基於node

  1. 同源策略是瀏覽器處於安全考慮,爲通訊設置了「相同的域、相同的端口、相同的協議」這一限制。這讓咱們的ajax請求存在跨域無權限訪問的問題。html

  2. 同時咱們發現script標籤引入腳本的行爲並不受同源策略的限制,可是script引入的文件會被當即執行,若是其內容不符合js語法,則會報錯;node

操做原理

針對以上狀況,誕生了jsonp:git

  1. 利用script標籤的src屬性來請求接口,並向接口傳遞一個回調函數(克服了同源問題)github

  2. 接口將數據以回調函數參數的形式同回調函數一同傳回;此時傳回則是這樣形式的一個字符串:回調函數名(數據),這樣就符合js語法了(克服了script標籤引入內容非js報錯的問題)ajax

實例操做

紙上得來總覺淺,絕知此事要躬行。jsonp的原理我早就倒背入流了,可是看着以爲明白,但總以爲少了點什麼沒抓住。因此,實際操刀試試吧。點擊下載源碼npm

下載代碼後,進入some-code/jsonp-demo文件夾,該文件夾的目錄爲:json

app.js跨域

package.json瀏覽器

views安全

  1. 命令行進入當前目錄,安裝包依賴:

    npm install
  2. 安裝完畢後,運行程序:

    node app.js

    若是看到命令行輸出「app is listening」則表示運行成功

  3. 修改host

    由於須要模擬跨域,因此在host文件中建立倆個不一樣的域名,在host文件中添加如下內容:

    127.0.0.1  www.a.com www.b.com

    自此結束,在瀏覽器中輸入http://www.a.com:3000/,若是訪問成功則表示大功告成,頁面中應該出現倆個按鈕。

這個時候,咱們打開瀏覽器的控制檯,分別點擊頁面中的倆個按鈕,就能夠看到測試結果啦。

代碼分析

  1. 入口文件:app.js

    • 設定模版引擎

      app.set('views', path.join(__dirname, 'views'));
      var swig = new swig.Swig();
      app.engine('html', swig.renderFile);
      app.set('view engine', 'html');
    • 設置路由和接口

      訪問www.a.com時,渲染view/index.html頁面

      app.get("/",function(req,res){
          res.render('index', {});
      })

      請求www.b.com/index.json時,返回數據,這裏服務器收到jsonp的回調函數名,並把它與數據拼接在一塊兒返回給客戶端

      //模擬數據
      var data = {"brand":23}
      app.get("/index.json",function(req,res){
      //解析請求路徑
      var param = urlLib.parse(req.url,true);
      var returnValue = param.query.callback+ '(' +           JSON.stringify(data) +')';
          res.send(returnValue)
      })
    • 啓動服務

      app.listen(3000,function(){
        console.log("app is listening")
      })
  2. 頁面:view/index.html

    頁面中有倆個按鈕:jsonp_buttonajax_button,點擊之後分別進行jsonp請求和ajax請求。

    • 綁定點擊事件

      jsonp_button.onclick = function(){
          var url = "http://www.b.com:3000/index.json?callback=jsonp";
          //向頁面中添加script標籤,進行jsonp請求
          creatScript(url)
      }
      
      ajax_button.onclick = function(){
      //ajax請求
          var xhr = getXhr();
          xhr.open("get","http://www.b.com:3000/index.json");
          xhr.send();
          if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                console.log(xhr.responseText);
            } else {
                console.log("Request was unsuccessful: " + xhr.status);
          }
      }
      function getXhr(){
          var xhr;
          if(window.XMLHttpRequest){      
              xhr = new XMLHttpRequest()
          }else{
              xhr = new ActiveXObject("Microsoft.XMLHTTP"); 
          }
          return xhr;
      }
    • 動態建立script標籤

      function creatScript(url){
          var scriptTag = document.createElement('script');
          scriptTag.setAttribute('src', url);
          document.getElementsByTagName('head')[0].appendChild(scriptTag);
      }
    • jsonp回調函數

      function jsonp(data) {
            //獲取數據
          console.log(data);
      }

由上面能夠得出:jsonp中全部請求數據的後續操做應寫在jsonp的回調函數中,它相似於ajax 的 success操做。

最後一句話歸納jsonp:jsonp就是本來應該發送json數據給客戶端的服務器,再也不發送json,改成發送一段調用回調函數的js代碼,而本來應該返回的數據則是該函數的參數。

相關文章
相關標籤/搜索