雜談:前端Web通信

前端Web通信

Web2.0以來航攒,Ajax的出世趴梢,解決了傳統(tǒng)表單提交頁面跳轉(zhuǎn)币他,閃爍白屏等問題。使得Web頁面可以實現(xiàn)局部更新灵莲,不僅減少了網(wǎng)絡(luò)帶寬,還大大提升了用戶體驗。

但Ajax并非是一把萬能的鑰匙,足以打開Web通信這扇大門碟摆,當(dāng)請求遇到跨域通信時,Ajax就沒轍了断盛。

Web的快速發(fā)展讓開發(fā)走向工程化的同時钢猛,要求工作維度進行劃分(前端后端分工明細),以便擴展維護日益復(fù)雜龐大的項目需求厢洞。而前后端分離的開發(fā)方式正是這種需求背景下衍生的產(chǎn)物躺翻。(以前混編的代碼現(xiàn)在是再也不想看到)

前后端分離的開發(fā)方式卫玖,如何進行數(shù)據(jù)通信是開發(fā)人員繞不過去的問題。作為開發(fā)同學(xué)的小伙伴客戶端的瀏覽器陕靠,有點小調(diào)皮還做了一個同源策略的限制脱茉,當(dāng)我們的數(shù)據(jù)請求遇到不同源的情況下(跨域),我們就得嘗試其它的通信方法税肪,不能Ajax一條道走到黑益兄。

什么是同源策略及限制

同源策略限制從一個源加載的文檔或腳本如何與來自另一個源的資源進行交互净捅。這是一個用于隔離潛在惡意文件的關(guān)鍵的安全機制。

同源要求協(xié)議荆永,域名具钥,端口(默認80)三者都相同捉腥,否則為非同源你画。

同源策略限制:

  • Cookie坏匪, LocalStorage和IndexDB無法讀取
  • Dom無法獲取
  • Ajax請求不能發(fā)送

前后端如何通信

  1. Ajax(僅支持同源)
  2. WebSocket (不受同源限制)
  3. CORS (都支持适滓,新的W3C通信標(biāo)準(zhǔn))

如何創(chuàng)建Ajax

  • XMLHttpRequest對象的工作流程
  • 兼容性處理
  • 事件的觸發(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ù)通信嗅绸,但是遇到跨域請求時,我們就得更換手中這把Ajax的鑰匙猛拴,來重新配鑰匙開鎖

跨域通信的幾種方式

  1. JSONP
  2. Hash
  3. postMessage (HTML5)
  4. WebSocket
  5. CORS (新的W3C通信標(biāo)準(zhǔn))

1. JSONP

JSONP原理:客戶端通過動態(tài)創(chuàng)建script標(biāo)簽異步加載來實現(xiàn)愉昆,服務(wù)端callback返回客戶端定義的方法名跛溉,讓客戶端進行調(diào)用獲取數(shù)據(jù)。

只支持Get請求 (GET與POST的區(qū)別這里暫不細講)

// 客戶端發(fā)送請求
<script src="http://www.abc.com?data=name&callback=jsonpname"></script>
<script>
jsonpname({
    data: {
        ...
    }
})
</script>

2. Hash

Hash原理:通過window.onhashchange事件監(jiān)聽來獲取url中hash值來實現(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)

項目中應(yīng)用場景:

  1. 頁面和其打開的新窗口的數(shù)據(jù)傳遞
  2. 多窗口之間消息傳遞
  3. 頁面與嵌套的iframe消息傳遞
  4. 上面三個問題的跨域數(shù)據(jù)傳遞

4. WebSocket

WebSocket是HTML5開始提供的一種在單個 TCP 連接上進行全雙工通訊的協(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是一個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) {
    // 錯誤
})

-- End --

JSONP有更好的兼容性疤估,能兼容低版本瀏覽器,但是基于Get傳輸數(shù)據(jù)钞瀑,會因為瀏覽器Url長度限制而限制數(shù)據(jù)大小雕什。CORS在不考慮低版本瀏覽器時贷岸,無疑是目前最好前后端通信方案(單向)偿警,雙向選擇WebSocket,而多個頁面之間的數(shù)據(jù)通信盒使,如內(nèi)嵌iFrame等,則推薦postMessage七嫌。

每種方案有不同的應(yīng)用場景少办,解決問題不只有一種解決方案,實際項目開發(fā)中诵原,需根據(jù)實際需求來挑選最優(yōu)的方案英妓。


參考資料

  1. html5 postMessage解決跨域、跨窗口消息傳遞
  2. 干貨 | 前端常用的通信技術(shù)
  3. 阮一峰 — 跨域資源共享 CORS 詳解
  4. CORS正確使用姿勢

作者:以樂之名
本文原創(chuàng)绍赛,有不當(dāng)?shù)牡胤綒g迎指出蔓纠。轉(zhuǎn)載請指明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惹资,一起剝皮案震驚了整個濱河市贺纲,隨后出現(xiàn)的幾起案子航闺,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畏吓,居然都是意外死亡,警方通過查閱死者的電腦和手機宏悦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門砖瞧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來储矩,“玉大人持隧,你說我怎么就攤上這事褥实「缤В” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我亚斋,道長,這世上最難降的妖魔是什么厚掷? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上欧穴,老公的妹妹穿的比我還像新娘涮帘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般桃序。 火紅的嫁衣襯著肌膚如雪奇适。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天菲宴,我揣著相機與錄音呜达,去河邊找鬼眉踱。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谈宛。 我是一名探鬼主播琼牧,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼侄柔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了薪者?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤陷谱,失蹤者是張志新(化名)和其女友劉穎烙博,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烟逊,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡渣窜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年乔宿,在試婚紗的時候發(fā)現(xiàn)自己被綠了坝橡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片番宁。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出片习,到底是詐尸還是另有隱情,我是刑警寧澤蹬叭,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布藕咏,位于F島的核電站,受9級特大地震影響秽五,放射性物質(zhì)發(fā)生泄漏孽查。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一坦喘、第九天 我趴在偏房一處隱蔽的房頂上張望盲再。 院中可真熱鬧,春花似錦瓣铣、人聲如沸答朋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绿映。三九已至,卻和暖如春腐晾,著一層夾襖步出監(jiān)牢的瞬間叉弦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工藻糖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留淹冰,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓巨柒,卻偏偏與公主長得像樱拴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子洋满,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容