jsonp是跨域請求的手段之一。php
先來看看下面這段代碼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('響應內容')");跨域
因爲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:'響應內容'})"; ?>
$.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; ?>