在完成上次簡單的測試之後,接下來將結合《javascript權威指南》關於jsonP例子,介紹如何動態請求和響應數據. 首先,我們需要編寫一個客戶端頁面,通過綁定事件的方式,向指定地址發送jsonP請求。
服務端1: Node . URL : http://localhost:3000
服務端2: Nginx+PHP . URL : http://localhost:8080
同一主機,不同端口符合同源策略。
首先我們現在設置服務端2的頁面,主要是產生一個可視化文檔,填寫參數向目的地發送請求。
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonP</title>
<script>
var getJSONP = { counter : 0}; // 管理jsonP請求次數 和 函數
function sendRequest(){
var q = document.getElementsByName("qname")[0].value; //取得 文本框數據
var url = "http://localhost:3000"; //設置爲 node 服務端 地址
if(typeof q !="undefined"){
url+="?q="+q; //附加參數
}
createJsonP(url,function(res){ //開始執行jsonP函數
console.log(res);
});
}
function createJsonP(url,callback){ // 發送請求 url 和 回調函數
console.log("start");
var cbnum = "cb" + getJSONP.counter++ ; // 每一次jsonP請求 都會進行統計 自增
var cbname = "getJSONP." +cbnum; // callback 回調函數唯一名稱
if(url.indexOf("?")==-1){
url+="?jsonp=" + cbname; //這裏的jsonp 鍵名是一個關鍵字,將與服務端1獲取get請求參數名一致。而鍵值則是請求成功後調用的函數名稱
}else{
url+="&jsonp=" + cbname;
}
var script = document.createElement("script"); // 創建一個script 元素
// 預先設置好 回調函數
getJSONP[cbnum] = function (res){ //設置script 元素的 src 之前 聲明好 回調函數.
try{
console.log(getJSONP);
callback(res); // 執行真正的 回調函數.
}finally{
// 執行完回調函數後 刪除輔助的回調函數 和 剛剛添加的script元素
delete getJSONP[cbnum];
script.parentNode.removeChild(script);
}
};
// 設置 請求地址 此時纔開始進行ajax請求 腳本
script.src = url;
document.documentElement.appendChild(script); //添加到 文檔裏面
}
</script>
</head>
<body>
<label for="">qname:</label>
<input type="text" id ="val" name="qname">
<button id="btn">開始請求</button>
</body>
<script>
window.onload = function (){
var btn = document.getElementById('btn');
btn.addEventListener("click",sendRequest,false);
}
</script>
</html>
接下來是Node環境裏處理該請求,實際上使用任何服務端腳本語言都可以,只要將返回的格式爲 callbak( json格式參數 ), 客戶端腳本就會執行 callback方法。
var express = require('express');
// 建立 express 實例
var app = express();
app.get('/', function (req, res) { // 監聽根目錄
var data = { name:"abc",type:"jsonP" , q : req.query.q };
var str = req.query.jsonp + '(' + JSON.stringify(data) + ')';//jsonp 是一個關鍵名 req.query.jsonp 就是獲取客戶端傳遞過來的 get請求中的jsonp鍵值
if(typeof req.query.q !="undefined"){
console.log("request q is "+str);
}
res.send(str); //返回符合格式的字符串
});
app.listen(3000, function (req, res) {
console.log('app is running at port 3000');
});
接下啦.我們進行一次測驗.首先查看客戶端頁面
我們在文本框填寫數據後,點擊按鈕.進行發送.這是會發送一個如下的get請求
可以看到getJSONP.cb0是我們第一次的回調函數名稱. 而getJSONP 對象的格式如下:
產生立一個cb0的屬性,屬性類型爲函數類型.
服務端1 在終端輸出的內容爲:
說明確實有請求進行訪問.同時返回的格式爲: getJSONOP.cb0({}); 這樣 當客戶端請求成功後 , 會執行getJSONP 對象裏的cb0函數。執行的結果就是調用真正的callback函數,將數據傳遞給callback函數.同時銷燬 getJSONP 對象的 cb0函數,
真正的callback函數 就會將我們的json 數據打印在客戶端控制檯中。
這樣,一個動態的設置參數請求jsonP的例子就介紹完了。實際上本身就是利用了script 元素可以引用外部任何javascript格式的腳本. 支持跨域,跨服務器.避免了同源策略的產生.
關於如何避免同源策略的問題,我們還得需要通過更多的例子進行介紹.