跨域JSONP

fengchao000 2020-03-05

一、什么是同源策略

同源策略:同源是指域名、协议、端口均相同

跨域:是指从一个域名的网页去请求另一个域名的资源,只要域名、协议、端口有一个不同,就被当作是跨域

JSONP是我们解决跨域最常用的方式

二、JSONP的原理

JSONP是JSON with Padding的简写,是一种跨域的解决方案

JSONP由两部分解组成:回调函数和数据。回调函数是当相应到来的时候,应该在页面中调用的函数,数据就是传回回调函数中的JSON数据

JSONP的原理:我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的,但是在用link标签和script标签引入其他域上的脚本文件是可以的,JSONP就是利用script标签上的src属性来加载不同域上的资源

JSONP重要的一点就是允许用户传递一个函数名作为参数传给服务端,然后服务端返回数据时,会将这个函数参数作为函数名来来包裹住数据,函数名(数据),这样客户端就可以随意定制自己的函数来自动处理返回数据了;例如我们传给服务端的函数名是abc,那么服务器端就会将我们所需要的数据作为abc函数的参数返回来abc(数据),服务端返回的数据是JSON格式的,这也是JSONP封装的思路

三、封装JSONP函数

function getJSONP(url,callback){
            if (!url) {
                return;
            } else {
            // 声明数组用来随机生成函数名,索引
            var a=[‘a‘,‘b‘,‘c‘,‘d‘,‘e‘,‘f‘,‘g‘,‘h‘,‘i‘,‘j‘],
            r1=Math.floor(Math.random()*10), //Math.floor()取整函数,这样r1,r2,r3就是随机的0-9
            r2=Math.floor(Math.random()*10),
            r3=Math.floor(Math.random()*10),
            name=‘JSONP‘+a[r1]+a[r2]+a[r3];
            cbname=‘getJSONP.‘+name; //随机生成的函数名要作为getJSONP的一个属性,方便后面删除delete getJSONP[name];
            // console.log(cbname);

            if(url.indexOf(‘?‘)===-1){
                url+=‘?jsonp=‘+cbname;
            }else{
                url+=‘&jsonp=‘+cbname;
            }
            // console.log(url);
            // 动态创建script标签,第1步,通过src引入js文件,
            var script=document.createElement("script");
            script.src=url;
            document.getElementsByTagName("head")[0].appendChild(script);
    //第2步,载入js文件后
            // 定义被脚本执行的回调函数,getJSON[name]这里要作为一个变量,所以要用[],而不能用.
            getJSONP[name]=function(data){    //第3步:执行url中指定的函数
                try{  //try里面是可能发生错误的;比如跨域获取没有成功或成功
                    callback&&callback(data);
                }catch(e){  //发生错误了可以捕获到
                    //
                }finally{  //不管有没有发生错误,都要执行的操作
                    //最后删除该函数及script标签,不删除的话产生数据会造成污染
                    delete getJSONP[name];
                    script.parentNode.removeChild(script);
                }
            }
            }
        }
        getJSONP(url,function(data){
            console.log(data); //这里的回调函数传到getSONP函数里面,在getJSONP[name]函数执行,getJSONP[name]函数传回来了跨域的数据data,所以最后将data传出来并打印
});

相关推荐