js跨域请求(jsonp)

时间:2022-11-21 21:44:20

jsonp是跨域请求的手段之一。

jsonp的原理:

先来看看下面这段代码

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
    </head>
    <script>
        function fn(response){
            alert(response);
        }
    </script>
    <body>
    </body>
    <script src='jsonp.js'></script>//注意这里:jsonp.js 这个js文件中其实只有一句话 fn('响应内容'); </html>

所以原理很简单,其实就是我们定义好了一个方法,然后后台返回一串字符串,而这个字符串又刚好就是一个函数的执行。

fn('响应内容')  这是js文件的内容,本身就是一个函数的执行。

类似:eval("fn('响应内容')");

封装jsonp:

由于ajax不能跨域,所以我们有必要封装一个跨域请求的jsonp方法。

function jsonpAsync(object){
        //默认参数
        var _object = {
            url:"",
            jsonp:"",
            request:{},
            callback:function(respose){}
        };

        //覆盖默认参数
        for(var key in object){
            _object[key] = object[key];
        }
        //生成一个唯一的方法名
        var fnName = 'jxf_' + new Date().getTime();
        //url参数拼接
        if(_object.url.indexOf('?') < 0){
            _object.url += '?';
        }
        for(var key in _object.request){
            if (key != 'jsonp') {
                _object.url += '&'+key + '=' + _object.request[key];
            };
        }
        _object.url += '&'+_object.jsonp + '=' + fnName;
        //创建script标签
        var scriptTag = document.createElement('script');
        //将方法注册到全局
        window[fnName] = function(response){
            try{
                _object.callback(response);
            }catch(e){
                console.log(e);
            }finally{
                //最后删除该函数与script元素
                scriptTag.parentNode.removeChild(scriptTag);
                delete window[fnName];//=null
            }
        }
        scriptTag.src = _object.url;
        document.getElementsByTagName('head')[0].appendChild(scriptTag);
    }

    jsonpAsync({url:'http://localhost:81/jsonp/jsonp.php',jsonp:'jsonp', callback:function(response) {
            alert(response.text);
    }});

简单点,后台就用php了

<?php 
    echo $_GET['jsonp']."({text:'响应内容'})";
?>

js跨域请求(jsonp)js跨域请求(jsonp)

 

Jquery中ajax中的jsonp:

$.ajax({
        type : "get",
        async: false,
        url : "http://localhost:81/jsonp/jsonp.php",
        dataType : "jsonp",
        jsonp: "jsonp",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名
        //jsonpCallback:"zidingyi",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名(类似:jQuery1102016820125747472048_1450147653563({text:'响应内容'}});)
        success : function(data){
            console.log(data);
        },
        error:function(){
            console.log('fail');
        }
    });

 

最后引用一篇比较完成的jsonp的封装:原文链接http://blog.csdn.net/liusaint1992/article/details/50959571

// 主要实现功能:
        // 1.参数拼装。
        // 2.给每个回调函数唯一命名。
        // 3.在回调成功或请求失败之后删除创建的JavaScript标签。 需要兼容IE。IE下onerror事件不兼容。这里有对它的模拟实现。在IE下加载失败也能get到。
        // 4.超时功能。超时取消回调。执行error。
        // 5.error事件。可执行自己传入的error事件。
        function JSONP(url,config){  
            var data = config.data || [];  
            var paraArr=[],paraString='';//get请求的参数。  
            var urlArr;  
            var callbackName;//每个回调函数一个名字。按时间戳。  
            var script,head;//要生成script标签。head标签。  
            var supportLoad;//是否支持 onload。是针对IE的兼容处理。  
            var onEvent;//onload或onreadystatechange事件。  
            var timeout = config.timeout || 0;//超时功能。  
          
            for(var i in data){  
                if(data.hasOwnProperty(i)){  
                    paraArr.push(encodeURIComponent(i) + "=" +encodeURIComponent(data[i]));  
                }  
            }  
          
            urlArr = url.split("?");//链接中原有的参数。  
            if(urlArr.length>1){  
                paraArr.push(urlArr[1]);  
            }  
          
            callbackName = 'callback'+new Date().getTime();  
            paraArr.push('callback='+callbackName);  
            paraString = paraArr.join("&");  
            url = urlArr[0] + "?"+ paraString;  
          
            script = document.createElement("script");  
            script.loaded = false;//为了实现IE下的onerror做的处理。JSONP的回调函数总是在script的onload事件(IE为onreadystatechange)之前就被调用了。因此我们在正向回调执行之时,为script标签添加一个属性,然后待到onload发生时,再检测有没有这个属性就可以判定是否请求成功,没有成功当然就调用我们的error。  
          
            //将回调函数添加到全局。  
            window[callbackName] = function(arg){  
                var callback = config.callback;  
                callback(arg);  
                script.loaded = true;  
            }  
          
            head = document.getElementsByTagName("head")[0];  
            head.insertBefore(script, head.firstChild) //chrome下第二个参数不能为null  
            script.src = url;  
          
            supportLoad = "onload" in script;  
            onEvent = supportLoad ? "onload" : "onreadystatechange";  
          
            script[onEvent] = function(){  
          
                if(script.readyState && script.readyState !="loaded"){  
                    return;  
                }  
                if(script.readyState == 'loaded' && script.loaded == false){  
                    script.onerror();  
                    return;  
                }  
                //删除节点。  
                (script.parentNode && script.parentNode.removeChild(script))&& (head.removeNode && head.removeNode(this));    
                script = script[onEvent] = script.onerror = window[callbackName] = null;  
          
            }  
          
            script.onerror = function(){  
                if(window[callbackName] == null){  
                    console.log("请求超时,请重试!");  
                }  
                config.error && config.error();//如果有专门的error方法的话,就调用。  
                (script.parentNode && script.parentNode.removeChild(script))&& (head.removeNode && head.removeNode(this));    
                script = script[onEvent] = script.onerror = window[callbackName] = null;  
            }  
          
            if(timeout!= 0){  
                setTimeout(function() {  
                    if(script && script.loaded == false){  
                        window[callbackName] = null;//超时,且未加载结束,注销函数  
                        script.onerror();                 
                    }  
                }, timeout);  
            }  
          
        }  

html

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <title>jsonp测试</title>  
    <script src="jsonp.js"></script>  
</head>  
<body>  
    <script>  
        function myerror(){  
            alert('there must be something wrong!');  
        }  
        function getData (data){  
            alert("服务器过来的数据是"+data);  
        }  
        var url = 'http://runningls.com/demos/2016/jsonp/jsonp.php';  
        //调用函数。  
        JSONP(url,{  
            data:{  
                id:1  
            },  
            callback:getData,  
            error:myerror,  
            timeout:10000  
        });  
    </script>  
</body> 

php

<?php   
  
$callback = $_GET['callback'];  
$id = $_GET['id'];  
  
if($id == 1){  
    $res = 'this is 1';  
}  
  
if($id == 2){  
    $res = 'this is 2';  
}  
  
$res = $callback."('$res')";  
  
echo $res;  
  
?>