JSONP完美实现方案

2 分钟阅读

AJAX可能是前端在开发中用到的最频繁的知识了,说起AJAX就不得不谈起AJAX的跨域问题,什么是跨域呢?

这里就要谈到浏览器的同源策略,不同域的客户端在没有明确的授权的情况下,是不允许读写对方的资源的。

那什么叫做跨域呢?

协议、域名和端口,只要有一个不同,就会出现跨域问题,当我们去自己的服务器请求资源或者去其他的服务器请求资源的时候,由于跨域的问题,我们会无法正确的请求到我们想要的资源,会引发页面的样式不正常或者字体不显示等等奇怪的问题,这个时候我们就需要跨域去请求资源。

前端有很多跨域的方式,比较常见的有:

  1. 设置window.domain
  2. 使用iframe
  3. 借助window.name
  4. 使用JSONP
  5. CORS

今天主要讲到的就是JSONP

什么是JSONP

JSONP 就是JSON WITH PADDING,顾名思义,就是以一种填充的方式将需要的数据填充到一个js里来进行获取。

在html中有一些标签是可以跨域访问资源的,例如script、img和link,JSONP实现原理就是借助script的可跨域性来获取数据的,不过因为script的src发送的只能是get请求,所以我们只能获取到get方式的接口传回的数据,下面附上JSONP的一个比较完美的实现方式,希望对大家有所帮助

text
/**
 * 自动发送 jsonp
 * @param {String} url
 * @param {Obj} data
 * @param {Function} callback
 */
function jsonp (url, data, callback) {
  var funcName = getFunctionName()
  data = data || {}
  data.callback = funcName
  url = parseUrl(url, serialize(data))

  window[funcName] = function (response) {
    callback(response)
  }

  createScript(url)
}

/**
 * 序列化参数
 * jsonp 中参数只能是 GET 方式传递
 * @param {Obj} data
 */
function serialize (data) {
  var ret = []

  Object.keys(data).forEach(item => {
    ret.push(encodeURIComponent(item) + '=' + encodeURIComponent(data[item]))
  })

  return ret.join('&')
}

/**
 * 处理 URL ,把参数拼上来
 * @param {String} url
 * @param {String} param
 */
function parseUrl (url, param) {
  return url + (url.indexOf('?') === -1 ? '?' : '&') + param
}

/**
 * 这里就是对 jsonp 的理解了,必须要有一个全局函数,而且不能重名
 */
function getFunctionName () {
  return ('jsonp_' + Math.random()).replace('.', '')
}

/**
 * 创建 script 标签并插到 body 中
 * @param {String} url
 */
function createScript (url) {
  var doc = document
  var script = doc.createElement('script')
  script.src = url

  doc.body.appendChild(script)
}
相关文章