js跨域請求(jsonp)

jsonp是跨域請求的手段之一。php

jsonp的原理:

先來看看下面這段代碼html

<!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>

因此原理很簡單,其實就是咱們定義好了一個方法,而後後臺返回一串字符串,而這個字符串又恰好就是一個函數的執行。ajax

chrome

fn('響應內容')  這是js文件的內容,自己就是一個函數的執行。

json

相似: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了app

<?php 
    echo $_GET['jsonp']."({text:'響應內容'})";
?>

 

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/50959571async

// 主要實現功能:
        // 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;  
  
?>  
相關文章
相關標籤/搜索