关于通信

1.同源策略

源:协议(http/https)+域名(www.baidu.com)+端口(一般默认80) 三个中有一个不一样,就是源不一样,就是跨域

不是同一个源限制

无法获取cookie,localStorage,indexDB

DOM无法获取

AJAX请求不能发送

2.如何创建AJax

//AJAX 可以使网页实现异步更新,整个网页不用空闲等待。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新

XMLHttpRequest对象的工作流程

(1).创建一个XMLHttpRequest对象

var xhr = createxmlHttpRequest();

//考虑兼容,是否支持XMLHttpRequest,

function createxmlHttpRequest() { 
  if (window.ActiveXObject) { 
    return new ActiveXObject("Microsoft.XMLHTTP"); 
  } else if (window.XMLHttpRequest) { 
    return new XMLHttpRequest(); 
  
}

(2).使用open设置和服务器的交互信息

method参数可以是GET、POST或PUT。url参数可以是相对URL或绝对URL。这个方法还包括3个可选的参数,是否异步,用户名,密码

xhr.open("method","URL",[asyncFlag],["userName"],["password"]) 

(3).使用send传送数据,开始和服务器交互

xhr.send(convertData(data))

function convertData(data){
if( typeof data === 'object' ){
var convertResult = "" ;
for(var c in data){
convertResult+= c + "=" + data[c] + "&";
}
convertResult=convertResult.substring(0,convertResult.length-1)
return convertResult;
}else{
return data;
}
}

(4).注册事件

xhr.onreadystatechange = function() { 
    if (xhr.readyState == 4) { 
      if(xhr.status == 200){
        ajaxData.success(xhr.response)
      }else{
        ajaxData.error()
      
    }
  

(5).刷新页面

3.跨域通信的几种方式

(1)jsonp

动态创建<script>标签,然后利用<script>的src 不受同源策略约束来跨域获取数据。

srcz中有一个回调函数callback=hanleFn

function handleFn(response){

  //response获取响应数据,只适合get请求

}

 

同一个主域名下的cookie跨域,如www.baidu.com和yun.baidu.com可以利用cookie的domain设置为.baidu.com,path表示当前cookie生效的目录

不同主域名,就可以使用jsonp

(2)hash

hash#后面的的改变不会刷新页面,search?后面的改变会刷新页面,所以hash可以做跨域通信

a.html首先创建一个隐藏的iframe,iframe的src指向localhost:8081/b.html,这时的hash值就可以做参数传递

b.html收到消息后通过parent.location.hash值来修改a.html 的hash值,从而实现数据传递

由于两个页面不在同一个域下,IE、Chrome不允许修改parent.location.hash的值,所以要借助localhost:8080域名下的一个代理iframe的c.html页面。

//数据直接暴露在了url中,数据容量和类型都有限等

(3)postMessage

 在A窗口中内嵌B窗口

<iframe id="iframe" src="http://xx.com/B.html"></iframe>
//在A窗口
var iframeWindow = document.getElementById('iframe').contentWindow;
iframeWindow.postMessage(msg,"http://xx.com/B.html"); //参数一:要传送的消息,参数二:目标源;若指定为”*“,则表示可以传递给任意窗口,指定为”/“,则表示和当前窗口的同源窗口
//在B窗口
window.addEventListener("message", function(e){
  if(e.origin === 'http://source.com') {
    document.getElementById('msg').innerHTML = e.data;
  }
}, false);

(4)websocket

 可以后台通知前端,不用前端一直轮询请求,等待后端响应。本身是支持不同源的,是可以跨域的

前端实现

源自阮一峰老师博客

http://www.ruanyifeng.com/blog/2017/05/websocket.html

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.");
}; 
后端的node实现参考
https://github.com/theturtle32/WebSocket-Node

(5)CORS

换句话说CORS是可以跨域的ajax通信

CORS简单请求(simple request)

浏览器自动在头信息之中,添加一个Origin字段(判断本次请求来自哪个源(协议 + 域名 + 端口))。服务器根据这个值,决定是否同意这次请求。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个Access-Control-开头头信息字段

若不在,则会抛出错误,但这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。

CORS非简单请求(not-so-simple request)。

非简单请求在正式请求前会发送一个“”预检“”请求,服务器对“预检”做出响应,如果否定则会报错,否则和简单请求一样正常请求

具体参考阮一峰老师http://www.ruanyifeng.com/blog/2016/04/cors.html

posted @ 2018-05-26 12:43  luosisi0202  阅读(175)  评论(1)    收藏  举报