前端面試準備--7.通信類

1.什么是同源策略及限制

1.同源策略限制從一個源加載的文檔或腳本與來自另一個源的資源進行交互。 ( 這是一個用于隔離潛在惡意文件的關鍵的安全機制。)
2.一個包括:協議域名端口
(這三個有一個不一樣就是源不一樣,就是我們所說的跨域了)
http:// 協議
www.xxx.com 域名
沒指名端口默認80
3.限制:不是一個源的文檔沒有權利去操作另一個源的文檔;

主要限制在幾個方面:

  • Cookie、LocalStorage 和 IndexDB 無法讀取
    --操作不了Cookie、LocalStorage、IndexDB
  • DOM無法獲得
    --無法獲取和操作另一個資源的DOM
  • Ajax請求不能發送(同源下的通信方式)
    --Ajax只適合同源的通信(跨域就不行了)

2.前后端如何通信

1、Ajax
--同源下的通信方式
2、WebSocket
--不受同源策略的限制
3、CORS
--支持跨域通信,也支持同源通信

3.如何創建Ajax

1、XMLHttpRequest對象的工作流程
2、兼容性處理
3、事件的觸發條件
4、事件的觸發順序

    function ajax(url,fnSucc,fnFaild){
    
        //1、創建一個對象(兼容IE6寫法)
        var xhr = XMLHttpRequest ? new XMLHttpRequest(): 
                  new ActiveXObject('Microsoft.XMLHTTP');
        
        //2、連接服務器,確定對象的發送方式:xhr.open(type,url,true);
        xhr.open('GET',url,true);
        
        //3、發送請求
        xhr.send();

        //4、接受服務器返回(響應)
        xhr.onreadyStateChange = function(){
        
            if(xhr.readyState == 4){//完成
                
     //如果加載媒體資源需要再加上xhr.status===206
    (媒體資源特別大,不是一次性返回過來的,是資源的一部分;服務端給你下發的http狀態碼是206,
     這個地方不加206,是收不到響應的)
                
                if (xhr.status === 200 || xhr.status === 304) {
                    fuSucc(xhr.responseText);
                }else{
                   if(fnFaild){
                     fnFaild(xhr.status);
                   }
                }
            }
            
        };
    }

4.跨域通信的幾種方式

1、JSONP

     1.在什么時候用:
     --在出現postMessage、CORS之前一直用JSONP做跨域通信的;
     2.怎么做到的:
       -- 利用script標簽的異步加載來實現的;
     (一個頁面是www.immoc.com,script標簽地址的域名100%不是(js的地址和域名是不一致的),
       跨源了,不影響script加載)--這就是jsonp能夠實行的一個最初的基本原理;
                    
     3.怎么實現的:
     --需要給服務端傳遞一個回調的名,這個回調的名就是我用加載script標簽的方式發出一個請求去,
    你給我返回一塊內容,這個內容是一個js塊也就是script的塊,這個塊中有回調名加代碼就能運行了,
            
--原理:(利用這個發出請求了,告訴服務端callback的名稱,將來要作為函數名來返回的,既然是函數名,
要創建一個函數,所以在調jsonp的時候 ,本地必須有一個jsonp的這么全局函數,后面才能把給的數據能
執行出來,當函數來運行。)
            
  callback后面名字叫什么都可以; 
  <script src="http://www.abc.com/?data=name&callback=jsonp"></script>
        
-告訴它一個回調的名稱,而且要在window注冊一個全局的一個函數,然后下面的createScript就是要動
態創建一個script標簽,最后返回這個東西。最后script.onload是監聽腳本的加載事件,如果響應完了,
也會響應onload,然后判斷onload是不是成功,成功了以后看能不能拿到那個數據。最后不要忘了刪除這
個函數變量window[callbackName]=null;最后往html中增加script標簽目的就是把這個請求發送出去。
        
        
3.1.1.服務器給你下發的是一個script內容,利用回調的東西,執行了后面的代碼
        <script>
            jsonp({
                data:{
                }
            });
        </script>
        
        jsonp.js:
        box({name:'xxx'});
        
        function createJs(sUrl){
            var oScript = document.createElement('script');
            oScript.type = "text/javascript";
            oScript.src = sUrl;
            document.getElementsByTagName('head')[0].appendChild(oScript);
        }
        
        createJs('jsonp.js?callback=box');
        
        function box(json){
            alert(json.name);
        }

2、Hash(url地址中#后面的東西)

        --Hash的變動頁面不會刷新
       url中?后面的叫search:search的改變是會刷新頁面的;所以search不能做跨域通信;
    
      // 利用hash,場景是當前頁面 A 通過iframe或frame嵌入了跨域的頁面 B,跨域給B發消息
      
      // 在A中偽代碼如下:
      var B = document.getElementsByTagName('iframe');
      B.src = B.src + '#' + 'data';
      
      // 在B中的偽代碼如下
      window.onhashchange = function () {
          var data = window.location.hash;
      };
      
      **跨域給B發消息:
      先拿到B這個窗口的地址src,然后通過hash的方式后面發一段字符串,這個字符串可以是通過
      完整的json,最后通過json.stringify()把json轉成字符串發給B,你是發出去了,B能不能接收
      到,B在自己的代碼中增加一個window.onhashchange,這個事件是用來監聽你當前頁面的hash有
      沒有改變。之前的頁面是src,現在的頁面加一個hash,所以對B來說,你的url的hash變化了,
      就可以拿到了。拿到了以后通過window.location.hash就能拿到hash的具體內容。
      window.location.hash可不是拿到一個,如果hash后面等于data除了A發送過來的東西還有別的
      拼接,回來要特殊處理一下。

3、postMessage(html5新增加的處理跨域通信的)

        同源策略的目標就是限制跨域通信,但是實際業務中又需要跨域通信;
        html5中出現了這個標準postMessage,用這個實現跨域通信;
        
          // 窗口A(http:A.com)向跨域的窗口B(http:B.com)發送信息
          Bwindow.postMessage('data', 'http://B.com');
          // 在窗口B中監聽
          Awindow.addEventListener('message', function (event) {
              console.log(event.origin);
              console.log(event.source);
              console.log(event.data);
          }, false);
          
        **怎么發送:
       在A窗口,給誰發送,要選中哪個窗口,調postMessage這個API,第一個參數是發送的數據部分,
       這里推薦使用字符串格式;第二個是接收方那個源,*是可以給任何窗口發送(很多窗口都能接收
       到你的信息,這個是不安全的),推薦的做法是加上一個源;

        **發送對方怎么接受:
            B窗口要做哪些事情呢?
            就是要監聽message事件,
            window.addEventListener('message',響應函數,true/false指定捕獲還是冒泡);
            要拿的就是下面這三個參數:
            //來判斷發送者的源,在你的響應程序中,你要選擇性的接收;比如我只接收來自A.com的
            信息,其他的一律不接收,那么就通過event.origin這個屬性來判斷
              console.log(event.origin);
              console.log(event.source);//引用A窗口的對象
              console.log(event.data);//發送的消息通過event.data拿到數據

4、WebSocket(不受同源策略限制的,拿來跨域通信正合適)

【參考資料】http://www.ruanyifeng.com/blog/2017/05/websocket.html

          1.聲明一個webSocket對象,這個地方有兩種,ws、wss區別一個加密一個非加密,
           后面指向服務器的一個地址,這樣就建立了相當于JS一個對象來管理這個鏈接。
          var ws = new WebSocket('wss://echo.websocket.org');
    
           2.請求發送出去
          ws.onopen = function (evt) {
              console.log('Connection open ...');
              ws.send('Hello WebSockets!');
          };
    
           3.對方給消息怎么接收,通過這個參數的data來拿到
          ws.onmessage = function (evt) {
              console.log('Received Message: ', evt.data);
              ws.close();
          };
    
          4.最后這個鏈接不用了,中斷了,監聽onclose來確定是不是關閉了
          ws.onclose = function (evt) {
              console.log('Connection closed.');
          };

5、CORS(Ajax一個變種,fetch實現CORS通信的--新出的通信標準,可以理解為支持跨域通信的Ajax)

【參考資料】http://www.ruanyifeng.com/blog/2016/04/cors.html

  Ajax是不能發送跨域通信的,瀏覽器在識別你用Ajax發送了一個跨域請求的時候,它會在你
  http頭中加一個orgin,來允許跨域通信。如果不加這個頭,就是一個普通的Ajax,遇到跨域通信,
  瀏覽器就會攔截了(非法的不允許請求)。
        
          
  // url(必選),options(可選),then就是回調成功,回調類似ES6的promise的寫法;
     catch就是捕獲錯誤。
          
          fetch('/some/url/', {
              method: 'get',
              }).then(function (response) {
    
                 }).catch(function (err) {
            // 出錯了,等價于 then 的第二個參數,但這樣更好用更直觀
          });
          
    *CROS為什么就能支持跨域的這種通信?   
    瀏覽器會攔截ajax請求,如果它覺得這個ajax請求是跨域的,它會在http請求中,加一個origin
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容