jsonp
@(我的第一个笔记本)
-
取数据:控制台----network----wd(关键词)-----cb(json格式数据返回时前面的函数名)
-
script
:可以跨域 ,是一个作用域
jsonp原理
三部曲:
- 定义了有名字的全局函数
- 通过script发生请求,请求必须在全局函数之后,因为要使用的东西必须在使用之前调用,预解释
- 当全局函数被调用的时候,会自动传入一个实参,就是请求的数据,在全局函数里面通过形参来接收这是实参传递的数据
-
根据上面的取数据的过程,我们可以
- 定义一个全局函数(名字和cb后面的名字一样),接收参数,要搜索的,里面存放请求返回的json格式的数据
- 那个cb,也就是函数名的调用,当通过一个script发起一个跨域请求的时候,就相当于调用了定义的全局函数,然后全局函数接收跨域请求传过来的参数(数据),最后取得返回的数据
-
传统的ajax是不能跨域请求的,要通过jsonp
封装ajax+jsonp库
ajax库使用时的设计
// jquery里面的ajax传入一个对象,不用记住参数的位置,只需要传入一个对象就行
ajax({
url: "test.php",// 请求地址
data: {'wd':'icessun'},// 前端传递给后台的数据,请求参数,最后使用对象传递
type: 'jsonp',//请求方式,(get(获取数据,显示在地址栏里面),post(提交数据,显示在请求体里面),jsonp)
jsonp: 'cb',// 回调函数的名字,jquery中默认是callback
dataType: 'json',// 返回数据类型
success:function(data){
console.log(data);
},// 数据请求成功
error:function(){
},// 数据请求失败
complete:function(){
},// 加载完成,数据请求结束
fnLoading:function(){
},// 等待加载,数据正在加载中
timeout:function(){
},// 请求超时
})
定义一个全局的ajax函数,按照上述设计使用
- 所有的类都是window的全局属性,故可以使用window.XMLHttpRequest来验证浏览器的高低,兼容浏览器
- 表单序列化:
$('form').serialize()
:把表单里面的数据拼接成key=value的方式传递 - 表单enctype:请求响应数据的方式
- 数组转字符串:join;字符串转数组:splite
// json2url json格式数据转字符串 key=value形式的字符串
function json2url(json){
// 避免缓存
json.t=Math.random();
var ary=[];
// 遍历对象
for(var attr in json){
ary.push(attr+'='+json[attr]);
}
return ary.join('&'); // 使用&拼接起来的字符串
}
// 字符串转为json格式数据
function jsonParse(jsonStr){
return 'JSON' in window? JSON.parse(jsonStr):eval('('+jsonStr+')');
}
// 考虑有几个参数
function ajax(opt){
// 传入了参数就接收,没有传就是空对象
opt=opt||{}; // 最多undefined
if(!opt.url) return; // 没有请求地址,直接阻断执行
// 默认值的设置
var data=opt.data||{};
var tyep=opt.type||{};
var jsonp=opt.jsonp||'callback';
var timeout=opt.timeout||3000;
var timer=null;
// ajax封装的四部曲
// 1 创建一个xml对象 判断浏览器是否支持XMLHttpRequest
if(window.XMLHttpRequest){
var xml=new XMLHttpRequest();
}else{
var xml=new ActiveXObject('Microsoft.XMLHTTP');
}
// 2 打开地址 考虑请求方式GET(打开的地址里面包含参数) POST(参数在请求体里面) JSONP 参数的传递方向不一样
// 3 发送请求
switch(type.toLowerCase()){
// toLowerCase() 严格比较 ===
case 'get': // 请求参数在地址栏
// get 请求 参数放在url里面传递
xml.open('get',opt.url+'?'+json2url(data),true);// true异步
xml.send(null);
break;
case 'post': // 请求参数在请求体
// post 请求,就相当于一个人,有头有体
xml.open('post',opt.url,true);
xml.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); // 设置请求头
xml.sned(json2url(data)); // 发送参数 请求体
break;
case 'jsonp':
// 创建一个有名的全局函数,名字里面不能有点 坑
var fnName='jsonp_'+Math.random();
fnName=fnName.replace('.','');
// 创建一个script 可以对本页面发起jsonp请求 data是一个对象
data[jsonp]=fnName; // 把fnName插入到data传递的参数里面
var oS=document.createElement('script');
oS.src=opt.url+'?'+json2url(data); // 发送请求,然后这个全局函数被调用window[fnName]
document.body.appendChild(oS);
// 在全局函数( window[fnName])里面接收实参
window[fnName]=function(val){
opt.success&&opt.success(val);
// script是用来发生请求的,当请求完毕,使script为null
document.body.removeChild(oS);
};
break;
}
// 正在加载
opt.fnLoading&&opt.fnLoading();
// 4 响应请求 异步操作
xml.onreadystatechange=function(){
if(xml.readyState==4){
opt.complete&&opt.complete(); // 加载完成
clearTimeout(timer);
// 是否成功
if(/^2\d{2}$/.test(xml.status)){
if(opt.dataType==='json'){
// 获取成功的数据,进行json格式的转变 opt.success&&opt.success(jsonParse(xml.reponseText));
}else{
json.success&&json.success(xml.reponseTest);
}
}else{
opt.error&&opt.error(xml.status);
}
}
}
// jsonp立即调用
if(type === 'jsonp') return;
// 等待超时,开启定时器
timer=setTimout(function(){
console.log('网络不行')
xml.onreadystatechange=null; // 不等待请求
},timeout)
}
网友评论