摘要:作為開發(fā)同學(xué)的小伙伴客戶端的瀏覽器,有點(diǎn)小調(diào)皮還做了一個(gè)同源策略的限制,當(dāng)我們的數(shù)據(jù)請求遇到不同源的情況下跨域,我們就得嘗試其它的通信方法,不能一條道走到黑。
Web2.0以來,Ajax的出世,解決了傳統(tǒng)表單提交頁面跳轉(zhuǎn),閃爍白屏等問題。使得Web頁面可以實(shí)現(xiàn)局部更新,不僅減少了網(wǎng)絡(luò)帶寬,還大大提升了用戶體驗(yàn)。
但Ajax并非是一把萬能的鑰匙,足以打開Web通信這扇大門,當(dāng)請求遇到跨域通信時(shí),Ajax就沒轍了。
Web的快速發(fā)展讓開發(fā)走向工程化的同時(shí),要求工作維度進(jìn)行劃分(前端后端分工明細(xì)),以便擴(kuò)展維護(hù)日益復(fù)雜龐大的項(xiàng)目需求。而前后端分離的開發(fā)方式正是這種需求背景下衍生的產(chǎn)物。(以前混編的代碼現(xiàn)在是再也不想看到)
前后端分離的開發(fā)方式,如何進(jìn)行數(shù)據(jù)通信是開發(fā)人員繞不過去的問題。作為開發(fā)同學(xué)的小伙伴客戶端的瀏覽器,有點(diǎn)小調(diào)皮還做了一個(gè)同源策略的限制,當(dāng)我們的數(shù)據(jù)請求遇到不同源的情況下(跨域),我們就得嘗試其它的通信方法,不能Ajax一條道走到黑。
什么是同源策略及限制同源策略限制從一個(gè)源加載的文檔或腳本如何與來自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。
同源要求協(xié)議,域名,端口(默認(rèn)80)三者都相同,否則為非同源。
同源策略限制:Cookie, LocalStorage和IndexDB無法讀取
Dom無法獲取
Ajax請求不能發(fā)送
前后端如何通信Ajax(僅支持同源)
WebSocket (不受同源限制)
CORS (都支持,新的W3C通信標(biāo)準(zhǔn))
如何創(chuàng)建AjaxXMLHttpRequest對象的工作流程
兼容性處理
事件的觸發(fā)條件
事件的觸發(fā)順序
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject("Microsoft") var data = opt.data, url = opt.url, type = opt.type.toUpperCase(), dataArr = []; for (var k in data) { dataArr.push(k + "=" + data[k]); } if (type === "GET") { url = url + "?" + dataArr.join("&"); xhr.open(type, url.replace(/?$/g, "", true); xhr.send(); } if (type === "POST") { xhr.open(type, url, true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send(data.join("&")); } xhr.onload = function() { if (xhr.status === 200 || xhr.status === 304) { var res; if (opt.success && opt.success instanceof Function) { res = xhr.responseText; if (typeof res === "string") { res = JSON.parse(res); opt.success.call(xhr, res) } } else { if (opt.error && opt.error instanceof Function) { opt.error.call(xhr, res); } } } }
同源下,我們可以直接使用Ajax來與后端同學(xué)做數(shù)據(jù)通信,但是遇到跨域請求時(shí),我們就得更換手中這把Ajax的鑰匙,來重新配鑰匙開鎖
跨域通信的幾種方式JSONP
Hash
postMessage (HTML5)
WebSocket
CORS (新的W3C通信標(biāo)準(zhǔn))
1. JSONPJSONP原理:客戶端通過動(dòng)態(tài)創(chuàng)建script標(biāo)簽異步加載來實(shí)現(xiàn),服務(wù)端callback返回客戶端定義的方法名,讓客戶端進(jìn)行調(diào)用獲取數(shù)據(jù)。
只支持Get請求 (GET與POST的區(qū)別這里暫不細(xì)講)
// 客戶端發(fā)送請求2. Hash
Hash原理:通過window.onhashchange事件監(jiān)聽來獲取url中hash值來實(shí)現(xiàn)數(shù)據(jù)傳輸。與Get一樣,有Url長度限制
// A中代碼 var B = document.getElementdByTagName("iframe"); B.src = B.src + "#" + "data"; // B中代碼 window.onhashchange = function(){ var data = window.location.hash; }3. postMessage
postMessage是HTML5的API,可參考開發(fā)文檔window.postMessage
// A.com向B.com發(fā)送信息 Bwindow.postMessage("data","http://B.com") // B中監(jiān)聽 window.addEventListener("message", function(event){ console.log(event.origin); // http://A.com console.log(event.source); // Bwindow console.log(event.data); // data }, false)
項(xiàng)目中應(yīng)用場景:
頁面和其打開的新窗口的數(shù)據(jù)傳遞
多窗口之間消息傳遞
頁面與嵌套的iframe消息傳遞
上面三個(gè)問題的跨域數(shù)據(jù)傳遞
4. WebSocketWebSocket是HTML5開始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議,本身不受同源限制。
// WebSocket代碼示例 var ws = new WebSocket("wss://echo.websocket.org"); ws.onopen = function (evt) { console.log("Connection open ..."); ws.send("Hello WebSocket!"); }; ws.onmessage = function (evt) { console.log("Received Message: " + evt.data); ws.close(); } ws.onclose = function (evt) { console.log("Connection closed."); }5. CORS
CORS是一個(gè)W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務(wù)器,發(fā)出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
瀏覽器兼容在XHR(IE8/9)及XHR2(>=IE10)下需要做兼容處理。
// CORS代碼示例 fetch("/url", { method: "get", }).then(function(res){ ... }).catch(function(err) { // 錯(cuò)誤 })-- End --
JSONP有更好的兼容性,能兼容低版本瀏覽器,但是基于Get傳輸數(shù)據(jù),會(huì)因?yàn)闉g覽器Url長度限制而限制數(shù)據(jù)大小。CORS在不考慮低版本瀏覽器時(shí),無疑是目前最好前后端通信方案(單向),雙向選擇WebSocket,而多個(gè)頁面之間的數(shù)據(jù)通信,如內(nèi)嵌iFrame等,則推薦postMessage。
每種方案有不同的應(yīng)用場景,解決問題不只有一種解決方案,實(shí)際項(xiàng)目開發(fā)中,需根據(jù)實(shí)際需求來挑選最優(yōu)的方案。
參考資料
html5 postMessage解決跨域、跨窗口消息傳遞
干貨 | 前端常用的通信技術(shù)
阮一峰 — 跨域資源共享 CORS 詳解
CORS正確使用姿勢
作者:以樂之名
本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。轉(zhuǎn)載請指明出處。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/96397.html
摘要:對的請求,也是要有一個(gè)了解,比如協(xié)議,請求方式,請求過程,結(jié)果狀態(tài)碼等。教程協(xié)議詳解經(jīng)典面試題一個(gè)故事講完響應(yīng)狀態(tài)碼上面提到響應(yīng)狀態(tài)碼,在這里也簡單寫下。 勸了別人無數(shù)次,讓別人喝了雞湯,幫別人填坑,自己卻掉了坑 1.前言 在前端學(xué)習(xí)里面,很多人都是注重學(xué)習(xí)代碼(html,css,js)?;蛘呤且恍┛蚣?,庫(jquery,vue,react),或者是各種工具(webpack,gulp)...
摘要:對的請求,也是要有一個(gè)了解,比如協(xié)議,請求方式,請求過程,結(jié)果狀態(tài)碼等。教程協(xié)議詳解經(jīng)典面試題一個(gè)故事講完響應(yīng)狀態(tài)碼上面提到響應(yīng)狀態(tài)碼,在這里也簡單寫下。 勸了別人無數(shù)次,讓別人喝了雞湯,幫別人填坑,自己卻掉了坑 1.前言 在前端學(xué)習(xí)里面,很多人都是注重學(xué)習(xí)代碼(html,css,js)。或者是一些框架,庫(jquery,vue,react),或者是各種工具(webpack,gulp)...
摘要:對的請求,也是要有一個(gè)了解,比如協(xié)議,請求方式,請求過程,結(jié)果狀態(tài)碼等。教程協(xié)議詳解經(jīng)典面試題一個(gè)故事講完響應(yīng)狀態(tài)碼上面提到響應(yīng)狀態(tài)碼,在這里也簡單寫下。 勸了別人無數(shù)次,讓別人喝了雞湯,幫別人填坑,自己卻掉了坑 1.前言 在前端學(xué)習(xí)里面,很多人都是注重學(xué)習(xí)代碼(html,css,js)?;蛘呤且恍┛蚣埽瑤欤╦query,vue,react),或者是各種工具(webpack,gulp)...
閱讀 1568·2021-11-17 09:33
閱讀 1118·2021-11-12 10:36
閱讀 2428·2019-08-30 15:54
閱讀 2451·2019-08-30 13:14
閱讀 2928·2019-08-26 14:05
閱讀 3304·2019-08-26 11:32
閱讀 3014·2019-08-26 10:09
閱讀 3009·2019-08-26 10:09