历史:为了解决从一个服务端文件(数据库)获取数据的一个问题,从首先的form表单提交开始,form表单下的submit方法,向服务端提交发起一个POST请求,然后服务端返回数据,客户端刷新页面得到数据,此时需要整体刷新,同时也不能跨越。

然后是动态创建图片方法,通过图片的src指向发起一个GET请求,也有诸多诟病。

跨域接着采用动态创建script标签,然后通过src发起一个GET请求,也成为SRJ方法。

跨域最后SRJ演变成JSONP。

跨域

1.用一个栗子更深入地了解JSONP

2.理解JSONP到底做了什么

3.理解jQuery的JSONP写法

4.JSONP为什么不能支持POST请求

总结:

1.动态创建script标签发起请求

button.addEventListener('click',function(e){
  let script = document.createElement('script')
  script.src = '/xxx'
  document.body.appendChild(script)
  script.onload = function(){};
  script.onerrpr = funcition(){};
})

首先,为页面的按钮添加一个点击事件 => 当按钮被点击时,创建一个script标签,并设置其src指向 => 接着将这个新创建的src添加到页面中去 => 最后设置当请求成功与请求失败之后的内容。

这种方法称为Server Rendered Javascript (SRJ)服务器返回的JavaScript,可以做到无刷新局部更新页面,不受域名限制。

但是,存在这种方法存在一定的耦合性,需要一个网页的前端对另一个网页的后端有一定的了解,所以为了避免这种尴尬,要解耦,就是服务端我不需要知道你是在做什么,我只需要做的是当你给我发了规范的请求,我就给你响应,拿到响应之后你爱咋咋地,我不关心。

所以请求方自己定义一个回调函数,操作返回的数据,而响应方只需要根据请求方的查询参数调用其回调。

请求方:

window.xxx = function(result){
  if(result === 'success'){}
  else{}
}
button.addEventListener('click',function(e){
  let script = document.createElement('script')
  script.src = '/xxx'
  document.body.appendChild(script)
  script.onload = function(){};
  script.onerrpr = funcition(){};
})

响应方:

fs.writeFileSync(
  `xxx.call(undefined,'success')`
)

响应方在请求成功时,调用请求方的函数,同时传入一个参数'success'。

业界为了规范,做了如下调整:

请求方:

let functionName = 'ck' + parseInt(Math.random * 100000,10)
window[functionName] = function(result){
  if(result === 'success'){}
  else{}
}
button.addEventListener('click',function(e){
  let script = document.createElement('script')
  script.src = '/xxx?callback=' + functionName
  document.body.appendChild(script)
  script.onload = function(){};
  script.onerrpr = funcition(){};
})

用随机数来表示创建的script标签

响应方:

通过查询这个随机函数并进行调用:

${query.callback}.call(undefined,'success')

这就是完整的动态创建script标签进行跨域请求。

如果把传回的参数以JSON格式返回,那么就是所谓的JSONP:

${query.callback}.call(undefined,{
  "success":ture,
  "anotherAttr":xxx
})

花括号内是JSON语法,左右各有Padding,JSON+Padding就是JSONP。

2.JSONP到底在做什么:

  1. 请求方动态创建一个script标签,其src指向响应方,同时传入一个查询参数?callback=functionName
  2. 响应方根据查询参数callback构造形如 functionName.call(undefined,'数据')
  3. 请求方接收到响应方传回来的数据,就会执行functionName函数
  4. 那么请求方就拿到了数据

3.jQuery中JSONP的写法:

$.ajax({
  url:"请求方",
  dataType:"jsonp",
  success:function(response){}
})

只需要写请求方,以jsonp的格式请求,然后设置请求成功得到数据后的操作。中间的callback和查询callback都会被省略。

4.理解为什么JSONP不能用POST方法;

首先,因为JSONP是通过动态创建script方法来实现的

其次,动态创建script方法是通过设置src指向来发送请求的,他的唯一的方法是GET方法,所以不支持POST方法。


永远年轻,永远热泪盈眶。