JSONP詳解


0、關於JSONP

什么的JSONP

JSONP(JSON with Padding)是資料格式 JSON 的一種“使用模式”,可以讓網頁從別的網域要資料。另一個解決這個問題的新方法是跨來源資源共享。(參考:https://zh.wikipedia.org/wiki/JSONP

JSONP的起源

  1. 曾經的Ajax不能跨域請求(現在的也不能,不過有cors)
  2. Web上使用script調用js文件不存在跨域問題(實際上,只要擁有src屬性的標簽都允許跨域,比如script,img,iframe)
  3. 那個時候,想要通過web端跨域訪問數據,只可以在服務器端設法把數據裝進js,然后客戶端調用
  4. 剛好這個時候JSON大行其道
  5. 所以,解決方案就出來,web端像調用腳本一樣來跨域請求服務器上動態生成的js文件
  6. 為了便於客戶端使用數據,逐漸形成了一種非正式傳輸協議,人們把它稱作JSONP。

JSONP用來做什么

通過JSONP的起源,我們大概也知道了JSONP就是為了跨域資源訪問的。

1、JSONP實現原理

我們知道,在script標簽中請求的js代碼,到客戶端之后,是能被自動執行的。

我們先構造一個后端(采用node實現):

var http = require('http');

var server = http.createServer((req, res) => {
  var sendObj = {
    url: req.url,
    name: 'test'
  };
  res.write(`callback(${JSON.stringify(sendObj)})`);
  res.end();
});

server.listen(9999, () => {
  console.log('started.')
});

我們要使用這個這個數據呢?可以用Ajax,可能會產生跨域問題

另外,可以用如下寫法:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JSONP TEST</title>
</head>
<body>
  <script>
  function callback(obj){
    console.log(obj);
  }
  </script>
  <script src="http://localhost:9999/abc"></script>
</body>
</html>

打開這個頁面后,我們會看到控制台會輸出一個對象Object {url: "/abc", name: "test"}, 也就是后端返回的對象。

當使用script請求地址時,會將返回的字符串,默認當成js解析。由於后端返回是的callback(xxx),所以會調用本地的callback函數。

從原理上來看,要使用JSONP,必須要后端返回相應的數據,這個就是JSONP的模式了,允許客戶端傳遞一個callback函數,后端將數據包裹在callback函數中返回。

從原理也能看出,JSONP並不要求必須傳遞JSON格式的數據,只要是JS函數能夠認可的數據都是可以傳遞的

2、封裝JSONP調用JSONP

知道了原理,我們很容易能夠實現一個jsonp的函數調用,代碼如下:

window.JSONP = function(url, callback){
  callback = callback || 'callback';
  var result;
  return new Promise((resolve, reject) => {
    var overwritten;
    var scriptEl = document.createElement('script');
    scriptEl.src = url + '?callback=' + callback;
    //加載完成后,刪除callback
    scriptEl.onload = function(){
      if(overwritten === undefined){
        delete window[callback];  
      }else{
        window[callback] = overwritten;
      }
      resolve(result);
    }
    //掛載一個callback到window上
    overwritten = window[callback]; //先保存一個,用完之后再還原
    window[callback] = function(data){
      result = data
    }
    document.head.appendChild(scriptEl);
  });
};

如何用?

window.JSONP('http://localhost:9999/abc').then((data) => {
  console.log(data);
});

3、擴展

在jQuery中,我們使用jsonp感覺就和使用ajax沒有區別,但實際上它們的底層實現實現是完全不一樣的,畢竟原理都不同。

雖然很多庫和框架都把jsonp封裝到了ajax中,但是一定要記得jsonp不是ajax的一個特例。

當前,除了用jsonp跨域之外,還可以采用服務端代理(通過不跨域的后端程序,發送webClient去請求數據,然后轉發),CORS(API服務器允許跨域的一種設置)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM