[聚合文章] JSONP原理及简单实现

JSONP 2017-08-30 15 阅读

全称 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)。

通过这种方式,即可实现跨域获取数据。

Code

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

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。