// 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)
})
//jquery的jsonp
// jQuery.getJSON(url[, data, callback])
// url: 请求地址
// data: 发送 Key/value 参数。
// callback: 载入成功时回调函数。
// $.getJSON(`http://localhost:8888/index.html?getdata=other&cb=?`, function(data){
// console.log('jsonP:',data)
// });
// $.ajax({
// url: `http://localhost:8888/index.html?getdata=other`,
// dataType: 'jsonp',
// jsonp: 'cb',
// type: 'get',
// success: (data)=> {
// console.log(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)
jQuery.getJSON(url, [data], [callback])