一、demo情景
1、通過gulp在本地開啟兩個服務器;
2、服務器協議相同、端口或者域名不同(通過gulp-connect設置)
3、后台用js文件模擬后台返回數據。(僅僅只是簡單的執行前台傳入的函數)
二、為封裝代碼寫法
1、服務器一中的 test1.js 文件
//4、jsonp跨域 //先定義一個callback函數,函數名要與后台一致 function jsonp(res){ console.log(res) } //js構建一個script標簽。並將src設置為請求地址url,且通過地址欄傳參格式將定義好的函數名作為參數傳入后台 var script = document.createElement("script"); script.src = "http://localhost:8080/js/index.js?callback=jsonp"; document.getElementsByTagName('head')[0].appendChild(script);
2、服務器二中的 test1.js 文件
//后台js直接執行回調函數,並將數據當作參數(只是模擬后台返回) //實際后台真正返回情況,並不是執行函數,而是將其拼接,用括號包裹參數類似於:callback+"("+$data+")" callback("我是后台數據")
三、jsonp封裝
1、服務器一中的 test1.js 文件
//5、jsonp封裝 function jsonpPakeage(obj) { //寫入url地址中的函數名稱,動態創建 var callbackName = "fn"+Math.random().toString().split("\.")[1]; //創建一個script標簽 var scriptObj = document.createElement("script"); obj.parames = obj.parames || ''; if (typeof obj.parames == 'object') { var arr = new Array(); for (var key in obj.parames) { arr.push(key + '=' + obj.parames[key]) } obj.parames = arr.join('&'); } //設置標簽的請求路徑 //像這樣:http://localhost:3000/api?callback=fn153498520409635392&id=1 scriptObj.src = obj.url + '?' + 'callback=' + callbackName + '&' + obj.parames; //將創建好的帶請求的script標簽添加到html的body中 document.getElementsByTagName('head')[0].appendChild(scriptObj); //這里必須這樣寫window[callbackName]; //如果寫window.callbackName會報錯沒有定義 //var one = true; window[callbackName] = function (res) { //if(one){ obj.success(res); //刪除的時候可以這樣寫 //由於請求一次會創建一個script標簽和一個函數,所以每次獲取到結果后就刪除 delete window.callbackName; document.getElementsByTagName('head')[0].removeChild(scriptObj); // one = false //} } } //調用 jsonpPakeage({ url:"http://localhost:8080/js/index.js", parames:"", success:function(res){ console.log(res) } })
2、服務器二中的 test1.js 文件,但這里由於是用js模擬的后台,所以拿不到服務器一傳過來的動態創建的callback函數名。所以測試的時候,我是將服務器一里面的callback函數名寫死。(后台在測試環境下拿不到動態函數名,所以內容不變)
//后台js直接執行回調函數,並將數據當作參數(只是模擬后台返回) //實際后台真正返回情況,並不是執行函數,而是將其拼接,用括號包裹參數類似於:callback+"("+$data+")" callback("我是后台數據")
四、參考
1、https://www.jianshu.com/p/0bad94e15d34
五、測試問題
1、測試的時候window[callback]會執行兩次,測試了幾次,問題有可能出在后台使用js模擬的,導致后台會執行一次callback函數。
2、如果后台不用js模擬還出現二次執行問題,可通過設置一個變量one並判斷從而禁止二次執行。(見測試代碼)
六、jsonp優劣
優點:它不像XMLHttpRequest對象實現的Ajax請求那樣受到同源策略的限制;它的兼容性更好,在更加古老的瀏覽器中都 可以運行,不需要XMLHttpRequest或ActiveX的支持;並且在請求完畢后可以通過調用callback的方式回傳結果。
缺點:它只支持GET請求而不支持POST等其它類型的HTTP請求;它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。