node_jsonp原理封装

// ajax 请求受同源策略影响,不允许进行跨域请求,而 script 标签 src 属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。


// 同源策略,
// 两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。
// 下列给出了相对http://store.company.com/dir/page.html同源检测的示例:
// 
// http://store.company.com/dir2/other.html          成功   只有路径不同
// http://store.company.com/dir/inner/another.html   成功   只有路径不同
// https://store.company.com/secure.html             失败  不同协议 ( https和http )
// http://store.company.com:81/dir/etc.html          失败  不同端口 ( http:// 80是默认的)
// http://news.company.com/dir/other.html            失败  不同域名 ( news和store )


// json 是一种数据交换格式
// jsonp 是一种非官方跨域数据交互协议
// 网购一件衣服(json),通过顺丰/圆通/申通/邮政(jsonp)送到你的手里
// jsonp的原理
// 1.Ajax直接请求普通文件存在跨域无权限访问的问题,不管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准
// 2.html调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)
// 3.于是设法把在远程服务器上的数据装进JSONP格式,而不是单纯的JSON。返回的是一段JS脚本(客户端的一个可执行的方法,参数为JSON 格式的数据,是要返回的数据)。如果单纯的返回JSON数据,虽然客户端也能看数据,但是却会报错,不能执行请求成功的回调函数。



// jsonp封装
// 接收两个参数,
// url:请求地址
// callback:回调函数
function jsonp (url,callback) {
  //创建script
  let script = document.createElement('script')
  // 将回调函数的名字拼接在url里,后端解析参数
  script.src = url + '&cb=getjsonP'
  // 当页面添加srcipt标签后,会自动请求src地址,不受同源限制
  // 相当于变相加载了js文件,会自动执行js文件的内容,保存就是getjsonP(data)
  document.querySelector('body').appendChild(script)
  // 定义回调函数,必须和url拼接的名字一样
  window.getjsonP = (data) => {
    callback(data)
  }
}
//jsonP调用
jsonp('http://localhost:8888/index.html?getdata=other', (data) => {
  console.log('jsonP:',data)
})

//nodejs后端
let http = require('http')
let fs = require('fs')
let url = require('url')
let querystr = require('querystring')
http.createServer((req, res) => {
  let urlObj = url.parse(req.url)
  let queryStrObj = querystr.parse(urlObj.query)
  if(queryStrObj.getdata)
    fs.readFile(__dirname+'/newsdata.json', (err, data)=> {
      // 解析url参数,获取回调函数的名字,将数据作为参数回调
      let template = `${queryStrObj.cb}(${data})` //json格式
      data = queryStrObj.cb ? template : data
      res.end(data)
    })
  else
    fs.readFile(__dirname+urlObj.pathname, (err, data)=> {res.end(data)})
}).listen(8888)

猜你喜欢

转载自www.cnblogs.com/JunLan/p/12441341.html