跨域解決方法——jsonp原理
技術標籤:web前端javascriptjsonp
跨域解決方法——jsonp原理
- 一個域名地址的組成:
- 當協議、子域名、主域名、埠號任意一個不相同時,都算作不同域,不同域之間相互請求資源,就算做“跨域”。由於瀏覽器同源策略的限制,非同源下的請求,都會產生跨域問題。
- 使用jquery的jsonp可以發起跨域請求,下面來探究下他的原理及使用。
首先看下如何使用script src=""來完成一個跨域請求:
普通的ajax請求是會發生跨域問題的,但是img的src,a的href,script的src卻可以發起任意網址的請求並接收到響應,於是我們首先利用script的src來完成一個跨域請求。
客戶端:
<script>
function show(weather){
document.write(weather)
}
//show('返回的資料');
</script>
<!--用請求引數將函式名傳遞給伺服器。-->
<script src="http://localhost:3000?callback=show"></script>
伺服器端:
const http = require("http"); const url = require("url"); http.createServer( (req,res)=>{ var Url = url.parse(req.url,true); //接收客戶端傳過來的名為callback的引數中儲存的函式名 var callback = Url.query.callback; var weather="北京 晴"; //將函式名動態拼接到要返回的函式呼叫語句中。 res.write(`${callback}("${weather}")`);//實際想要在客戶端執行的函式呼叫語句。 res.end(); } ).listen(3000);
script只能識別js語句,一旦接收到js語句就立即執行。於是在伺服器端拼接一條函式呼叫的js語句,並且提前在客戶端定義一個函式,當客戶端接收到伺服器返回的js語句後就會立即執行。
為了使函式名在客戶端可修改,於是用請求引數將函式名從客戶端傳遞給伺服器。
動態建立script元素
script是在頁面中寫死的,只能在頁面載入過程中執行一次,如果想每次單擊按鈕,隨時傳送請求,可以每次單擊按鈕時動態建立script元素。
<body>
<button>傳送請求</button>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js" ></script>
<script>
function show(weather){
alert(weather);
$("body>script:last").remove();//刪除建立的那個script元素
}
//show('返回的資料');
$("button").click(function(){
var script = document.createElement('script');
script.src="http://localhost:3000?callback=show";
document.body.appendChild(script);
})
</script>
</body>
jQuery對jsonp方式跨域進行了終極簡化
1.服務端程式碼不變,js程式碼如下:
最簡單的方式,只需配置一個dataType:‘jsonp’,就可以發起一個跨域請求。
jsonp指定伺服器返回的資料型別為jsonp格式,可以看發起的請求路徑,自動帶了一個callback=xxx,xxx是jquery隨機生成的一個回撥函式名稱。//callback: jQuery34105977893922582984_1578207815633
_: 1578207815634
這裡的success就跟上面的show一樣,如果有success函式則預設success()作為回撥函式。
<body>
<button>傳送請求</button>
<script src="jquery.js"></script>
<script>
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp", //其實也是動態建立script,藉助script傳送跨域請求,必須有服務端的支援,
success: function(weather) {
alert(weather);
}
})
})
</script>
</body>
2.再看下如何指定特定的回撥函式:
jsonpCallback: “show”,
看請求引數 callback: show_: 1578208620937,請求時帶的引數是:callback=show;呼叫回撥函式的時候,先呼叫了指定的show,然後再呼叫了success。所以,success是返回成功後必定會呼叫的函式,就看你怎麼寫了。
<script>
function show(weather) {
alert("show"+weather);
}
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp",
jsonpCallback: "show", //指定特定的回撥函式
success: function(weather) {
alert(weather);
}
})
})
</script>
3.再看看如何改變callback這個名稱:
jsonp: “func”,
看請求資訊:func: show_: 1578208954673
<script>
function show(weather) {
alert("show"+weather);
}
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp",
jsonp: "func", //改變callback這個名稱
jsonpCallback: "show",
success: function(weather) {
alert(weather);
}
})
})
</script>
指定callback這個名稱後,後臺也需要跟著更改。
http.createServer(
//每當有客戶端發來請求時,自動呼叫一下回調函式。
(req,res)=>{
var Url = url.parse(req.url,true);
//接收客戶端傳過來的名為callback的引數中儲存的函式名
var callback = Url.query.func;
var weather="北京 晴";
//將函式名動態拼接到要返回的函式呼叫語句中。
res.write(`${callback}("${weather}")`);//實際想要在客戶端執行的函式呼叫語句。
res.end();
}
).listen(3000);
總結
jsonp的實現方式其實也是動態建立script,藉助script傳送跨域請求,jquery中ajax的jsonp對這個複雜的過程進行了封裝,並且需要服務端的支援,所以可想而知,jsonp是不支援POST方式的。
jsonp的原理:
動態建立script標籤,並且自動給script的src屬性加入了callback引數,藉助script來發送跨域請求,請求結束後script會被自動刪除。並且必須有伺服器端配合接收callback儲存的函式名,服務端將要返回的資料填充到函式呼叫語句裡返回,客戶端收到js語句執行。