博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端通信、跨域
阅读量:4704 次
发布时间:2019-06-10

本文共 5003 字,大约阅读时间需要 16 分钟。

首先了解什么是同源策略:

限制一个源加载的文档或脚本与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。(来自MDN的解释)

源包括三个部分:协议、域名、端口(HTTP协议的默认端口是80)。如果其中有任何一个部分不同,则源不同。即为跨域。

限制:这个源的文档没有权利去操作另一个源的文档。这个限制体现在:

Cookie、LlocalStorage和IndexDB无法获取;

无法获取和操作DOM;

不能发送Ajax请求。(Ajax只适合同源的通信)。

 

前后端的通信方式:

Ajax:不支持跨域;

WebSocket:不受同源策略的限制,支持跨域;

CORS:不受同源策略的限制,支持跨域;一种新的通信协议标准。可以理解成同时支持同源和跨域的Ajax。

 

如何创建Ajax:

在回答 Ajax 的问题时,要回答以下几个方面:

  • 1、XMLHttpRequest 的工作原理

  • 2、兼容性处理

XMLHttpRequest只有在高级浏览器中才支持。在回答问题时,这个兼容性问题不要忽略。

  • 3、事件的出发条件

  • 4、事件的触发顺序

XMLHttpRequest有很多触发事件,每个事件是怎么触发的。

发送Ajax请求的五个步骤(XMLHttpRequest的工作原理)

1.创建XMLHttpRequest对象;

2.使用open方法设置请求的参数。open(method,url,是否异步)

3.发送请求;

4.注册事件。使用onreadystatechange事件,状态改变时就会调用。如果要在数据完整请求返回才调用需要加一些状态判断;

5.获取返回的数据,更新UI

发送get请求和post请求:

get请求举例:

    
Document

Ajax 发送 get 请求

 

post请求举例:

    
Document

Ajax 发送 get 请求

 

onreadystatechange事件:

注册onreadystatechange事件后,每当readyState属性改变时,就会调用onreadystatechange函数。

readyState:(存有XMLHttpRequest的状态。从0到4变化)

0:请求未初始化;

1:服务器连接已建立;

2:请求已接收;

3:请求处理中;

4:请求已完成,且响应已就绪

 

事件的触发条件

 

 事件的触发顺序

 

原生Ajax请求

var util = {};    //获取 ajax 请求之后的json    util.json = function (options) {        var opt = {            url: '',            type: 'get',            data: {},            success: function () {            },            error: function () {            },        };        util.extend(opt, options);        if (opt.url) {            //IE兼容性处理:浏览器特征检查。检查该浏览器是否存在XMLHttpRequest这个api,没有的话,就用IE的api            var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');            var data = opt.data,                url = opt.url,                type = opt.type.toUpperCase();            dataArr = [];        }        for (var key in data) {            dataArr.push(key + '=' + data[key]);        }        if (type === 'GET') {            url = url + '?' + dataArr.join('&');            xhr.open(type, url.replace(/\?$/g, ''), true);            xhr.send();        }        if (type === 'POST') {            xhr.open(type, url, true);            // 如果想要使用post提交数据,必须添加此行            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");            xhr.send(dataArr.join('&'));        }        xhr.onload = function () {            if (xhr.status === 200 || xhr.status === 304) { //304表示:用缓存即可。206表示获取媒体资源的前面一部分                var res;                if (opt.success && opt.success instanceof Function) {                    res = xhr.responseText;                    if (typeof res === 'string') {                        res = JSON.parse(res);  //将字符串转成json                        opt.success.call(xhr, res);                    }                }            } else {                if (opt.error && opt.error instanceof Function) {                    opt.error.call(xhr, res);                }            }        };    }

 

跨域通信的几种方式:

1.JSONP

2.WebSocket

3.CORS

4.Hash

5.postMessage

 

1.JSONP

原理:通过<script>标签的异步加载来实现。例如通过<script>标签的src,里面放url,加载一些插件,就用到JSONP。

实现:<script src="http://www.smyhvae.com/?data=name&callback=myjsonp"></script> 

上面的src中,data=name是get请求的参数,myjsonp是和后台约定好的函数名。

服务器端这样写:

myjsonp({            data: {}        })

于是,本地要求创建一个myjsonp 的全局函数,才能将返回的数据执行出来。

实际开发中前端的JSONP的实现:

 

2.WebSocket

代码实例如下:

var ws = new WebSocket('wss://echo.websocket.org'); //创建WebSocket的对象。参数可以是 ws 或 wss,后者表示加密。    //把请求发出去    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.');    };

 

3.CORS

fetch是一个比较新的API,用来实现CORS通信。用法如下:

// url(必选),options(可选)      fetch('/some/url/', {          method: 'get',      }).then(function (response) {  //类似于 ES6中的promise      }).catch(function (err) {        // 出错了,等价于 then 的第二个参数,但这样更好用更直观      });

另外,如果面试官问:“CORS为什么支持跨域的通信?”

答案:跨域时,浏览器会拦截Ajax请求,并在http头中加Origin。

 

4.Hash

url的#后面的内容就叫Hash。Hash的改变,页面不会刷新。这就是用 Hash 做跨域通信的基本原理。

补充:url的?后面的内容叫Search。Search的改变,会导致页面刷新,因此不能做跨域通信。

场景:我的页面 A 通过iframe或frame嵌入了跨域的页面 B。

现在,我这个A页面想给B页面发消息,怎么操作呢?

(1)首先,在我的A页面中:

//伪代码    var B = document.getElementsByTagName('iframe');    B.src = B.src + '#' + 'jsonString';  //我们可以把JS 对象,通过 JSON.stringify()方法转成 json字符串,发给 B

(2)然后,在B页面中:

// B中的伪代码    window.onhashchange = function () {  //通过onhashchange方法监听,url中的 hash 是否发生变化        var data = window.location.hash;    };

 

5.postMessage()方法

场景:窗口 A (http:A.com)向跨域的窗口 B (http:B.com)发送信息。步骤如下。

(1)在A窗口中操作如下:向B窗口发送数据:

// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息    Bwindow.postMessage('data', 'http://B.com'); //这里强调的是B窗口里的window对象

(2)在B窗口中操作如下:

// 在窗口B中监听 message 事件    Awindow.addEventListener('message', function (event) {   //这里强调的是A窗口里的window对象        console.log(event.origin);  //获取 :url。这里指:http://A.com        console.log(event.source);  //获取:A window对象        console.log(event.data);    //获取传过来的数据    }, false);

 

 

参考:

https://www.cnblogs.com/smyhvae/p/8523576.html

转载于:https://www.cnblogs.com/lhh520/p/10198283.html

你可能感兴趣的文章
如何恢复oracle中已删除的表
查看>>
双向BFS(转)
查看>>
【最短路】Dijkstra+ 链式前向星+ 堆优化(优先队列)
查看>>
linux下实现keepalived+nginx高可用
查看>>
【BZOJ3791】作业
查看>>
Html Agility Pack解析Html(C#爬虫利器)
查看>>
GridView中的CheckBox选中 (JQuery)
查看>>
webform(四)简单控件
查看>>
验证码
查看>>
敏捷开发入门教程
查看>>
C#发现之旅(收藏)
查看>>
POJ1125 Stockbroker Grapevine 多源最短路
查看>>
HDU 2126 Buy the souvenirs
查看>>
顺序容器的insert使用方法
查看>>
Markdown的使用
查看>>
销售系统学习.mdl
查看>>
触发器
查看>>
mysql配置默认字符集为UTF8mb4
查看>>
WPF实现3D翻转的动画效果
查看>>
自定义圆环进度条
查看>>