欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

postMessage及webSocket跨域方案詳解

 更新時(shí)間:2022年10月11日 10:58:56   作者:mouche  
這篇文章主要為大家介紹了postMessage及webSocket跨域方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、postMessage

我們?cè)谏弦黄?a href="http://www.dbjr.com.cn/article/264734.htm" rel="external nofollow" target="_blank">小白也能搞懂的JSONP和CORS跨域方案已經(jīng)說(shuō)過(guò)兩種跨域方案了,這一篇就再繼續(xù)講講postMessagewebsocket這兩種方案,它們也能算得上是跨域方案??

?是什么

  • window.postMessage() 方法提供了一種受控機(jī)制來(lái)規(guī)避此限制,只要正確的使用,這種方法就很安全
  • 聽(tīng)聽(tīng)MDN的解釋?zhuān)阂粋€(gè)窗口可以獲得對(duì)另一個(gè)窗口的引用,然后在窗口上調(diào)用 targetWindow.postMessage() 方法分發(fā)一個(gè) MessageEvent 消息。接收消息的窗口可以根據(jù)需要自由處理此事件

?語(yǔ)法

targetWindow.postMessage(message, targetOrigin, [transfer]);
  • targetWindow: 其他窗口的一個(gè)引用,比如 iframecontentWindow 屬性、執(zhí)行window.open返回的窗口對(duì)象、或者是命名過(guò)或數(shù)值索引的window.frames (en-US)
  • message: 將要發(fā)送到其他 window 的數(shù)據(jù)。它將會(huì)被結(jié)構(gòu)化克隆算法 (en-US)序列化。這意味著你可以不受什么限制的將數(shù)據(jù)對(duì)象安全的傳送給目標(biāo)窗口而無(wú)需自己序列化。
  • targetOrigin: 通過(guò)窗口的 origin 屬性來(lái)指定哪些窗口能接收到消息事件,其值可以是字符串*(表示無(wú)限制)或者一個(gè) URI。在發(fā)送消息的時(shí)候,如果目標(biāo)窗口的協(xié)議、主機(jī)地址或端口這三者的任意一項(xiàng)不匹配它提供的值,那么消息就不會(huì)被發(fā)送;只有三者完全匹配,消息才會(huì)被發(fā)送。這個(gè)機(jī)制用來(lái)控制消息可以發(fā)送到哪些窗口;
  • transfer 可選: 是一串和 message 同時(shí)傳遞的 Transferable 對(duì)象。這些對(duì)象的所有權(quán)將被轉(zhuǎn)移給消息的接收方,而發(fā)送一方將不再保有所有權(quán)。

通過(guò)以上敘述我們能夠了解到它的作用就是可以安全地給目標(biāo)窗口發(fā)送自定義的信息

?怎么用

有信息的發(fā)送,自然也要有信息的接收,我們可以采用addEventLister,監(jiān)聽(tīng)message事件: 該事件接收到消息時(shí)觸發(fā)

  • 我們先在同一個(gè)窗口對(duì)其進(jìn)行測(cè)試(在Origin值為http://127.0.0.1:5500/的頁(yè)面打開(kāi))
const data = {
  name : '某車(chē)',
  like:  '前端'
}
//傳入的message為data,targetOrigin為http://127.0.0.1:5500/
window.postMessage(data, 'http://127.0.0.1:5500/');
window.addEventListener('message',(event)=>{
//監(jiān)聽(tīng)該回調(diào)事件并打印
  console.log(event);
})
  • 我們看一下打印臺(tái),可以看到里面的data正是我們傳入的數(shù)據(jù),origin是發(fā)送消息的源,source為發(fā)送消息的窗口引用(后面這兩個(gè),用于我們回發(fā)消息,實(shí)現(xiàn)消息互通)

?如何跨域

上述我們提到了其他窗口的引用可以是iframecontentWindow屬性,也可以是window.open的返回值那么我們就都來(lái)試試看

iframe + postMessage

  • 這里是使用3300端口父頁(yè)面向內(nèi)嵌子頁(yè)面3301端口發(fā)送消息
//a.html
 <!-- 使用iframe,src指向3301端口 -->
<iframe src="http://127.0.0.1:3301/b.html" id="frame" onload="load()"></iframe>
<script>
const data = {
  name : '某車(chē)',
  like:  '前端'
}
const load = function(){
  //負(fù)責(zé)發(fā)布消息
  let frame = document.getElementById('frame'); 
  const targetWindow = frame.contentWindow;//得到目標(biāo)窗口的引用
  targetWindow.postMessage(data, 'http://127.0.0.1:3301'); //發(fā)送新消息
  //也監(jiān)聽(tīng)信息
  window.onmessage = function(event) {
    console.log(event.data)
  }
}
</script>
  • 這里記得在onload事件里面去觸發(fā),否則會(huì)報(bào)如下錯(cuò)誤

  • 3301端口監(jiān)聽(tīng)message事件,然后通過(guò)event.source得到3300端口頁(yè)面的引用,event.origin獲取3300端口的源,然后可以回發(fā)消息
    //b.html
    window.addEventListener('message',(event)=>{
      console.log(event.data);
      event.source.postMessage('我可以回發(fā)消息給你', event.origin);
    })

3300端口頁(yè)面的打印 (圖片端口號(hào)打錯(cuò)了,懶得修改了..)

window.open()+postMessage

先認(rèn)知一下window.open()語(yǔ)法

window.open(url, [name], [configuration])
  • url:為要新打開(kāi)頁(yè)面的url
  • name:為新打開(kāi)窗口的名字,可以通過(guò)此名字獲取該窗口對(duì)象
  • configuration:為新打開(kāi)窗口的一些配置項(xiàng),比如是否有菜單欄、滾動(dòng)條、長(zhǎng)高等等信息

還是上面的思路,我們讓3300端口3301端口發(fā)送信息

   //a.html
  <button class="openWindow">打開(kāi)窗口</button>
  <script>
    const btn = document.querySelector('.openWindow');
    const data = {
      name : '某車(chē)',
      like:  '前端'
    }
    //點(diǎn)擊之后,執(zhí)行window.open()
    btn.addEventListener('click', ()=>{
     const targetWindow =  window.open('http://127.0.0.1:3301/b.html', '3001端口'); //拿到目標(biāo)窗口的引用
     setTimeout(()=>{
      targetWindow.postMessage(data, 'http://127.0.0.1:3301/'); //發(fā)送數(shù)據(jù)
     },1000)
    })
    //同時(shí)監(jiān)聽(tīng)message事件
    window.addEventListener('message',(event)=>{
      console.log(event.data);
    })
  </script>
  • 3301端口監(jiān)聽(tīng)message事件,并且回發(fā)信息
    //b.html
    window.addEventListener('message',(event)=>{
      console.log(event.data);
      event.source.postMessage('我可以回發(fā)消息給你', event.origin);
    })
  • 看一下控制臺(tái)結(jié)果

3301端口打印如下

3300端口打印如下

?兼容性

還是在IE有兼容問(wèn)題

小結(jié):postMessage()方法允許來(lái)自不同源的腳本進(jìn)行有限的通信,只要能獲取到源和窗口對(duì)象就可以實(shí)現(xiàn)跨域消息傳遞

二、webSocket

  • webSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,能更好的節(jié)省服務(wù)器資源和帶寬并達(dá)到實(shí)時(shí)通訊的目的
  • WebSocketHTTP都是應(yīng)用層協(xié)議,都基于 TCP 協(xié)議
  • 只需要一次握手(使用HTTP協(xié)議)客戶(hù)端和服務(wù)端就可以建立持久性的鏈接,進(jìn)行雙向數(shù)據(jù)傳輸

?出現(xiàn)的原因

  • 需要實(shí)現(xiàn)“聊天室”,“消息推送”,“實(shí)時(shí)動(dòng)態(tài)”等功能
  • 曾經(jīng)的方案:
    • 短輪詢(xún);每隔一段時(shí)間就詢(xún)問(wèn)一次服務(wù)器是否有新的消息,缺點(diǎn)就是有一定的延遲,浪費(fèi)資源
    • 長(zhǎng)輪詢(xún):客戶(hù)端發(fā)送請(qǐng)求后如果數(shù)據(jù)沒(méi)有更新的話服務(wù)器就先將其掛起,有新消息則傳回,等傳回后又重新發(fā)起請(qǐng)求等待數(shù)據(jù)更新,缺點(diǎn)就是服務(wù)器需要保持大量的連接

?連接流程

  • 客戶(hù)端先用Upgrade:Websocket請(qǐng)求頭的HTTP請(qǐng)求,向服務(wù)器發(fā)起握手請(qǐng)求
Connnection:Upgrade  //表示要升級(jí)協(xié)議
Upgrade: websocket //表示要升級(jí)為websocket協(xié)議
Sec-webSocket-Version:13 //版本
  • 握手成功后,即升級(jí)協(xié)議,兩端就可以相互傳遞消息了

?兼容性

為什么說(shuō)它是解決跨域的方案:因?yàn)樗旧砭筒皇芡床呗缘南拗?,客?hù)端可以和任意服務(wù)器之間進(jìn)行通信

跨域小結(jié)

  • JSONP因?yàn)閮H支持get請(qǐng)求,淘汰無(wú)人問(wèn)津是遲早的事情
  • CORS支持所有類(lèi)型的HTTP請(qǐng)求,是跨域HTTP請(qǐng)求的根本解決方案,但是我們上一篇也提了,還是有IE兼容問(wèn)題
  • postMessage方法允許來(lái)自不同源的腳本進(jìn)行有限的通信,只要能獲取到源和窗口對(duì)象就可以實(shí)現(xiàn)跨域消息傳遞
  • websocket本身不受同源策略的限制,可以在不同源間進(jìn)行通信
  • 最后還有nginx反向代理,它可以說(shuō)基本沒(méi)啥毛?。坎贿^(guò)我不怎么了解它就不介紹啦??

以上就是postMessage及webSocket跨域方案詳解的詳細(xì)內(nèi)容,更多關(guān)于postMessage webSocket跨域的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論