# 前端通信

# 1.同源策略

  • 同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键安全机制
  • 什么是源:协议、域名与端口。这三者任何一个不一样的话,就算是跨域
  • 什么是限制:不是一个源的文档,没有权限去操作另一个源的文档
  • 限制为
    • cookie,localStorage和IndexDB无法读取
    • DOM无法获得
    • ajax请求无法发送
  • cookie的域名共享:共享之间的二级域名必须是解析于同一个顶级域名之下,就是把两个域名的cookie域设置为同一个顶级域名

# 2.前后端如何通信

  • Ajax 支持同源通信
  • WebSocket 不受同源策略影响
  • CORS 既支持同源通信也支持跨域通信

# 3.如何创建ajax

# XMLHttpRequest对象的工作流程

util.json=function(options){
  var opt = {
    url: '',
    type: 'get',
    data: {},
    success: function(){},
    error: function(){}
  }
  util.extend(opt, options) // 此处应实现一个深拷贝
  if(opt.url){
    var xhr=XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject()
    var url=opt.url,
        type=opt.type.toUpperCase(),
        data=opt.data,
        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(dataArr.join('&'))
    }
    xhr.onload=function(){
      if(xhr.status===200||xhr.status===304 || xhr.status===206){ //若是媒体资源,增加206状态码,媒体资源比较大,是部分返回
        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)
        }
      }
    }
  }
}

# 4.跨域通信的几种方式

# JSONP(只支持GET请求)

  • 原理: 通过 script 标签的异步加载来实现的。利用script标签不受同源策略的限制,天然可以跨域的特性。
<script>
var script = document.createElement('script');
script.type = 'text/javascript';

script.src = 'https://api.asilu.com/geo/&callback=jsonp';//这个是获取当前经纬度的接口
document.head.appendChild(script);//创建并添加script标签到<head>下

// 回调执行函数
function jsonp(res) {
    console.log(res);//打印jsonp返回的信息
}
</script>

# Hash

  • url中#号后面的部分为hash, hash的变动,你的页面不会刷新
  • url中?号后面的部分为search, search的改变会刷新页面,故search不可以做跨域通信

# postMessage

  • H5中新增的postMessage()方法,可以用来做跨域通信

# webSocket

  • WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现
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(现代浏览器普遍跨域解决方案)

  • 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信