JSONP原理及簡單實現


全稱 JSON with Padding,用於解決AJAX跨域問題的一種方案。

由於同源策略的限制,瀏覽器只允許XmlHttpRequest請求當前源(域名、協議、端口)的資源,而對請求script資源沒有限制。通過請求script標簽實現跨域請求,然后在服務端輸出JSON數據並執行回調函數,這種跨域的數據的方式被稱為JSONP。

實現原理

1.首先在客戶端注冊一個callback方法,放到window對象上,如:

callbackFunction (json) {
    console.log(JSON)
}

然后把callback的名字(callbackFunction)傳給服務器。

2.服務器先生成 JOSN 數據。

3.將 JOSN 數據直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文檔(如callbackFunction(JOSN)),返回給客戶端。

4.客戶端瀏覽器,將返回的JS標簽插入DOM,解析script標簽后,會執行callbackFunction(JOSN)。

通過這種方式,即可實現跨域獲取數據。

import { JSONP } from './JSONP'
// 調用
JSONP({
  url: 'url',
  data: {  
    key1: 'key1'  
  },  
  callback (data) {  
    // data 是服務端返回的數據  
  }  
})
// JSONP.js
let JSONP = (config = {}) => {
  let { data, url, callback } = config
  // 拼接請求Url
  if (!url) throw new Error('url is required!')
  let name = `id_${(new Date()).getTime()}_${Math.random().toString().substr(2)}`
  let srcUrl = getSrcUrl(url, {
    data,
    callback: name
  })
  // 插入Script標簽
  let script = document.createElement('script')
  script.type = 'text/javascript'
  script.src = srcUrl
  script.id = name
  // CallBack 放到 window 對象,調用后銷毀
  window[name] = function (json) {
    // 執行這個函數后,要銷毀這個函數
    window[name] = undefined
    // 獲取這個script的元素
    var elem = document.getElementById(name)
    // 刪除head里面插入的script,這三步都是為了不影響污染整個DOM啊
    removeElem(elem)
    // 執行傳入的的函數
    callback && typeof callback === 'function' && callback(json)
  }
  var head = document.getElementsByTagName('head')
  if (head && head[0]) {
    head[0].appendChild(script)
  }
}
let getSrcUrl = (url, data) => {
  let _url = url + (url.indexOf('?') === -1 ? '?' : '&')
  let ret = ''
  if (typeof data === 'string') {
    ret = data
  } else if (typeof data === 'object') {
    for (let key in data) {
      ret += '&' + key + '=' + encodeURIComponent(data[key])
    }
  }
  ret = ret.substr(1)
  return _url + ret
}
let removeElem = (elem) => {
  let parent = elem.parentNode
  if (parent && parent.nodeType !== 11) {
    parent.removeChild(elem)
  }
}
export default JSONP

注意

  1. 在 jquery 中,JSOP 被封裝在 $.ajax() 方法中,但是他的實現原理與 ajax 完全不同。
  2. JSONP的兼容性較好,在更加古老的瀏覽器中都可以運行,不需要XMLHttpRequest或ActiveX的支持。
  3. JSONP只支持GET請求而不支持POST等其它類型的HTTP請求。
  4. JSONP在調用失敗的時候不會返回各種HTTP狀態碼(解決方法:添加timeout參數,雖然JSONP請求本身的錯誤沒有被捕獲,但是最終會因為超時而執行error回調)。
  5. 在使用JSONP的時候必須要保證使用的JSONP服務必須是安全可信的。萬一提供JSONP的服務存在頁面注入漏洞,它返回的javascript都將被執行,若被注入這是非常危險的。


免責聲明!

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



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