前端面試11:通訊類

明易發表於2018-12-05

課程思維導圖

通訊類.png

Q:什麼是跨域通訊?

一個域下的文件或指令碼試圖去請求另一個域下的資源

Q:什麼是同源策略?

  1. 同源:協議、域名、埠
  2. 非同源的限制:
    1. cookie、localStorage、indexDB無法讀取
    2. DOM無法獲得
    3. Ajax 請求不能傳送

Q:前後端通訊有哪些?

  1. Ajax : 同源下的通訊方式
  2. WebSocket:不受同源策略限制
  3. CORS:支援跨域通訊,也支援同源通訊

Q:如何建立建立Ajax?

// 完整版
function ajax(opt) {
    if(!opt.url) return;
    var xhr = XMLHttpRequest
        ? new XMLHttpRequest()
        : new ActiveXObject('Microsoft.XMLHTTP');
     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);
         xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
         xhr.send(dataArr.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);
             }
         }
     };
}
// 簡易版,只考慮GET方式
var xhr = new XMLHttpRequest();
var url = '/test';
xhr.open('GET', url, true);
/**
 * 監聽服務端跟客戶端通訊的過程和進度
 */
xhr.onreadystatechange = function () {
    /**
     * 每當 readyState 改變時,就會觸發 onreadystatechange 事件。
     * 4: 請求已完成,且響應已就緒
     */
    if (xhr.readyState === 4) {
        // 200 成功
        if (xhr.status === 200) {
            console.log(xhr);
        } else {
            console.log('error');
        }
    }
}
xhr.send();//發起客戶端請求
複製程式碼

Q:跨域解決方案有哪些?

方案1:document.domain:

  1. 場景:兩個網頁一級域名相同,只是二級域名不同
  2. 方案:瀏覽器允許通過設定document.domain共享 Cookie。這種方法只適用於 Cookie 和 iframe 視窗,LocalStorage 和 IndexDB 無法通過這種方法

方案2:通過jsonp跨域

// 客戶端實現:
<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';
 
    // 傳參並指定回撥執行函式為onBack
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
    document.head.appendChild(script);
 
    // 回撥執行函式
    function onBack(res) {
        alert(JSON.stringify(res));
    }
</script>
// 服務端(返回時即執行全域性函式)
onBack({"status": true, "user": "admin"})
複製程式碼

方案三:location.hash

場景:當前頁面 A 通過iframe或frame嵌入了跨域的頁面 B

// 在A中虛擬碼如下:
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'data';
// 在B中的虛擬碼如下:
window.onhashchange = function () {
  var data = window.location.hash;
};
複製程式碼

方案四:postMessage

HTML5引入跨文件通訊API,這個API為window物件新增了一個window.postMessage方法,允許跨視窗通訊,不論這兩個視窗是否同源

// 例如,視窗A(http:A.com)向跨域的視窗B(http:B.com)傳送資訊
var popup = window.open('http://B.com', 'title');
popup.postMessage('Hello World!', 'http://B.com');
// 在視窗B中監聽
window.addEventListener('message', function (event) {
      console.log(event.origin);    // 訊息發向的網址
      console.log(event.source);    // 傳送訊息的視窗
      console.log(event.data);      // 訊息內容
}, false);
複製程式碼

方案五:WebSocket

var ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = function (evt) {
    console.log('Connection open ...');
    ws.send('Hello WebSockets!');
};
ws.onmessage = function (evt) {
    console.log('Received Message: ', evt.data);
    ws.close();
};
ws.onclose = function (evt) {
    console.log('Connection closed.');
};
複製程式碼

方案六:CORS

  fetch('/some/url/', {
      method: 'get',
  }).then(function (response) {
  }).catch(function (err) {
    // 出錯了,等價於 then 的第二個引數,但這樣更好用更直觀
  });
複製程式碼

相關文章