大家在初學(xué)的時候經(jīng)常遇到下圖這樣的報錯:
上圖是什么錯誤呢榜掌?
原來是因為瀏覽器有某些安全級別的限制,同源策略讲坎,所以在進(jìn)行瀏覽器端的web應(yīng)用開發(fā)的時候关筒,經(jīng)常會遇到跨域問題。
同源策略:
只有在同源的情況下(同域名驶睦,同協(xié)議砰左,同端口)才能進(jìn)行數(shù)據(jù)交互。
常用的跨域方式:
jsonp场航,cors缠导,服務(wù)端代理。
jsonp
是一種前后端結(jié)合的跨域問題解決方式:
原理:
動態(tài)的創(chuàng)建script標(biāo)簽溉痢,將script標(biāo)簽的src屬性設(shè)置成請求的目標(biāo)地址僻造,和后端商議之后,設(shè)置callback回調(diào)函數(shù)孩饼,利用回調(diào)函數(shù)來接收數(shù)據(jù)并進(jìn)行使用髓削。
為什么使用script:
依靠html中標(biāo)簽的src屬性不受同源策略的影響來實現(xiàn)的,而script標(biāo)簽接收到數(shù)據(jù)之后可以進(jìn)行數(shù)據(jù)的處理,所以一般選用script標(biāo)簽镀娶,
為什么要動態(tài)的創(chuàng)建script標(biāo)簽:
script只能執(zhí)行一次或者說只能請求一次立膛,所以說當(dāng)我們要不斷的進(jìn)行jsonp請求的時候,每一次的請求都需要一個script標(biāo)簽梯码,所以需要動態(tài)去創(chuàng)建script標(biāo)簽,script標(biāo)簽?zāi)軐⒄埱蟮降淖址當(dāng)?shù)據(jù)當(dāng)成js代碼去運行宝泵,所以我們可以依靠后端返回一段(執(zhí)行某個函數(shù),且給此函數(shù)傳入數(shù)據(jù))的這樣一段字符串來實現(xiàn)忍些,這樣的話鲁猩,script請求到該字符串之后,就會執(zhí)行該函數(shù)罢坝,且該函數(shù)能接收到數(shù)據(jù)廓握。
為什么需要和后端商議之后才能設(shè)置callback函數(shù):
因為后端開發(fā)者并不知道前端準(zhǔn)備來接收數(shù)據(jù)的函數(shù)是哪個函數(shù),所以需要讓前端通知后端接收數(shù)據(jù)的函數(shù)名,前端需要將函數(shù)名傳遞給后端嘁酿,但是傳遞的時候是以鍵值對的方式傳遞過去的隙券,所以需要前端將鍵值對的鍵名事先告知后端
注意:
獲取數(shù)據(jù)且操作完成后,一定要將創(chuàng)建的script標(biāo)簽去掉闹司,將隨機(jī)函數(shù)的內(nèi)存給釋放
缺點:
只能做get請求
//封裝jsonp
function Jsonp(options) {
//獲取對象的url屬性
let url = options.url
//判斷有沒有url
if(!url){console.error('url不合法');return ;};
let success = options.success || function(){}
//創(chuàng)建新函數(shù)準(zhǔn)備接收數(shù)據(jù)
var fname = 'jsonp'+Date.now()
//掛載全局函數(shù)
window[fname] = function(result){
//執(zhí)行成功回調(diào)并傳入回調(diào)函數(shù)
success(result)
//移除script標(biāo)簽
script.remove()
//移除全局函數(shù)
delete window[fname]
}
//動態(tài)創(chuàng)建script標(biāo)簽
url+='?cb='+fname
var script = $('<script>')
script.prop("src",url).appendTo($("body"))
}
Jsonp({
url:'http://localhost:3000/text',
success:function (results) {
console.log(results)
}
})
我希望用自問自答的形式能幫助大家更好的理解jsonp娱仔,其實官方?jīng)]有給出前端跨域的解決方法,但是我們偉大的程序猿自己摸索出來的解決跨域的一種方法jsonp游桩;是不是很厲害牲迫?