前端通信类的问题,主要包括以下内容:
1、什么是同源策略及限制 同源策略是一个概念,就一句话。有什么限制,就三句话。能说出来即可。
2、前后端如何通信 如果你不准备,估计也就只能说出ajax。
3、如何创建Ajax Ajax在前后端通信中经常用到。做业务时,可以借助第三方的库,比如vue框架里的库、jQuery也有封装好的方法。但如果让你用原生的js去实现,该怎么做?
这就是考察你的动手能力,以及框架原理的掌握。如果能写出来,可以体现出你的基本功。
4、跨域通信的几种方式 这部分非常重要。无非就是问你:什么是跨域、跨域有什么限制、跨域有几种方式。
下面分别讲解。
同源策略的概念和具体限制 同源策略:限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。(来自MDN官方的解释)
具体解释:
(1)源包括三个部分:协议、域名、端口(http协议的默认端口是80)。如果有任何一个部分不同,则源不同,那就是跨域了。
(2)限制:这个源的文档没有权利去操作另一个源的文档。这个限制体现在:(要记住)
Cookie、LocalStorage和IndexDB无法获取。
无法获取和操作DOM。
不能发送Ajax请求。我们要注意,Ajax只适合同源的通信。
前后端如何通信 主要有以下几种方式:
Ajax:不支持跨域。
WebSocket:不受同源策略的限制,支持跨域。
CORS:不受同源策略的限制,支持跨域。一种新的通信协议标准。可以理解成是:同时支持同源和跨域的Ajax。
如何创建Ajax 关于Ajax请求,可以看本人的基础文章:Ajax入门和发送http请求
在回答 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请求举例:
DocumentreadyState:(存有 XMLHttpRequest 的状态。从 0 到 4 发生变化)
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
事件的触发条件
事件的触发顺序
上图的参考链接:
你真的会使用XMLHttpRequest吗? 实际开发中用的 原生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); } } }; }Ajax 的推荐链接:https://segmentfault.com/a/1190000006669043
跨域通信的几种方式 方式如下:
1、JSONP
2、WebSocket
3、CORS
4、服务端代理
5、postMessage
6、nginx
上面这五种方式,在面试时,都要说出来。
1、JSONP 面试会问:JSONP的原理是什么?怎么实现的?
在CORS和postMessage以前,我们一直都是通过JSONP来做跨域通信的。
JSONP的原理:通过
JSONP的实现:
比如说,客户端这样写:
<script src="http://www.smyhvae.com/?data=name&callback=myjsonp"></script>上面的src中,data=name是get请求的参数,myjsonp是和后台约定好的函数名。 服务器端这样写:
myjsonp({ data: {} })于是,本地要求创建一个myjsonp 的全局函数,才能将返回的数据执行出来。
实际开发中,前端的JSONP是这样实现的:
2、WebSocket 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.'); };Websocket的推荐链接:http://www.ruanyifeng.com/blog/2017/05/websocket.html
3、CORS Cross-origin resource sharing 跨域资源共享 cors这里只需要后端在这个接口设置请求头就好了,例如 Access-Control-Allow-Origin
另外,如果面试官问:“CORS为什么支持跨域的通信?”
答案:跨域时,浏览器会拦截Ajax请求,并在http头中加Origin。 4.服务端代理 后端帮我们做中间层,帮我们发出跨域的请求,后端拿到请求到的数据在返回给我们,
因为后端是没有跨域这一个说法的,所以也不存在跨域这个问题
5、postMessage()方法 H5中新增的postMessage()方法,可以用来做跨域通信。既然是H5中新增的,那就一定要提到。
场景:窗口 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);6.nginx nginx的反向代理 我们前端一般在开发的时候会用到配置proxy的代理请求来解决跨域的问题,但是到线上了的时候,就没办法通过proxy,所以就需要配置nginx反向代理我们的请求,来解决跨域的问题,
