一、Ajax
Asynchronous JavaScript and XML。
Ajax 是一种用于创建快速动态网页的技术。其最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
常用于以下场景:
- 运用 JavaScript 渲染/操作 DOM 来执行动态效果
- 运用 XMLHttpRequest 或新的 Fetch API 来与服务器进行异步数据交互(json或xml)
流程:
Create a XMLHttprequest object -> httprequest -> Server -> process the returned data using javascript -> render page
1. 原生 JavaScript 实现 Ajax
var xmlhttp;
if(window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }
else{ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
/* 版本的浏览器IE6 IE7等不支持XMLHttpRequest对象,因此要使用ActiveXObject()对象来实现 */
/* get */
xml.onreadystatechange = function() {
if(xml.readyState==4&&xml.status==200) { var data = JSON.parse(xml.responseText); }
else { alert("请求失败"); }
}
xml.open("get", "url", "true"); //true表示置为异步请求
xml.send(null);
/* post */
xml.onreadystatechange = function(){
if(xml.readyState==4&&xml.status==200) { var data=JSON.parse(xml.responseText); }
else { alert("请求失败"); }
}
xml.open("post", "url", "true");
xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
/* 默认情况下 Ajax 会以 Content-Type: text/plain 方式来提交数据,此时服务器将忽略 post body 部分的数据,导致服务器无法获得请求的数据 */
xml.send(null);
2. readState 和 status
XMLHttpRequest.readyState:请求的状态
- 0 - 未初始化,还没有调用send方法
- 1 - 载入,已调用send方法,正在发送
- 2 - 载入完成,send方法执行完成,已经接收到全部相应内容
- 3 - 交互,正在解析相应内容
- 4 - 完成,响应内容解析完成,可以在客户端调用
XMLHttpRequest.status:请求过程中的状态说明
- 2xx - 成功
- 1xx - 表示临时响应,客户端在收到常规响应时,应配置接收一个或多个1xx 响应
- 3xx - 表示重定向,客户端必须采取更多操作来实现请求。例如,浏览器不得不请求服务器上的不同的页面,或需要通过代理服务器重复该请求。如 304 表示可以使用缓存,该请求重复了
- 4xx - 表示客户端错误。例如,客户端请求不存在的页面,或客户端未提供有效的身份验证信息
- 5xx - 表示服务器错误
二、跨域
No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Oringin ‘http://localhost’ is therefore not allowed access.
- 什么时候会出现跨域的问题?
请求非同源的资源时。
- 什么是同源?
所谓同源,就是指同域名,同端口,同协议下的资源。基于安全考虑,浏览器采用了同源策略,通过。浏览器对 JavaScript 脚本的限制,防止某些用户恶意获取其他用户的非法数据。所以当在某个服务器中的页面里,用户直接请求不支持跨域的服务器中的资源时,会出现上面的错误提示。
- 什么是跨域
所谓跨域,就是指跨域名,跨端口,跨协议。
例如,如果有两个服务器,服务器A和服务器B,服务器A上存储了.java,.js,.css等文件,当我们在服务器B上只写了html,然后要在服务器B上动态创建 .js,.css等数据(使用ajax请求),便向服务器A上请求这些文件,当请求这些文件后,我们再在服务器B上运行html,会发现在服务器B上的运行效果与在服务器A上运行的效果是一样的,这样就是实现了跨域。
但由于同源策略,所以一般都是不支持跨域的。
1. 方式一:利用 <script> 标签 src 属性不受同源策略影响
var oBtn = document.getElementById('btn');
oBtn.onclick = function() {
/* 不带callback函数 */
var _script = document.createElement("script");
_script.src = "http://test.com/api/User.php?user="+_user+"message="+_message;
_script.type = "text/javascript";
/* 带callback函数 */
var script = document.createElement("script");
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
};
2. 方式二:jQuery jsonp 和 getJSON
jsonp:json with padding,填充式json
/* $.get jsonp */
$(document).ready(function() {
$.get("http://10.9.156.108/HTML5/lesson24/test.js", null, function(){}, "jsonp");
});
/* $.ajax jsonp */
$.ajax({
async: true,
url: “https://api.douban.com/v2/book/search”,
type: “GET”,
datatype: “jsonp”,
jsonpCallback: “handleResponse”,
data: {
a: "",
count: 1
},
Success: function(res, status, xhr) {
Console.log(response);
}
});
/* getJSON */
/* 若不带参数默认不跨域,带了参数则支持跨域 */
$.getJSON("https://api.douban.com/v2/book/search") //默认不跨域
$.getJSON("https://api.douban.com/v2/book/search?callback=?", //加上callback参数支持跨域
function(data) { console.log(data); });
$.getJSON("https://api.douban.com/v2/book/search?q=javascript&count=1&callback=?",
function(data) { console.log(data); });
注意,jsonp 不能发送 post 请求,只要是使用 jsonp 方式,则请求一定是 get 方式,因为本质是 script 方式加载的
jsonp 存在的问题:如果所请求的其他域是不安全的,很可能会在响应中夹带一些恶意代码。
3. 方式三:CORS
CORS 定义一种跨域访问的机制,可以让 AJAX 实现跨域访问,CORS 允许一个域上的网络应用向另一个域提交。
场景:当你在本地开发前端业务,此时需要跟服务器上的后台业务进行数据交互时,本地计算机和远程服务器很明显是不同源的,此时可以让服务器后台的开发者通过 CORS 方式来允许前端的跨域请求:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-methods: POST,GET,DELETE,PUT,OPTIONS")
- Node JS 实现的后台业务
App.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With, yourHeaderFeild');
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if(req.method == 'OPTIONS') { // options请求是查看服务端支持什么方式的请求
res.send(200);
} else {
next();
}
})
4. 方式四:配置代理
我们在使用如 vue、react 等前端框架开发时,会发现它们在前后端分离的前提下,实现跨域请求的方式是在配置文件中添加代理。具体可以根据具体应用谷歌。