Ajax 和 请求跨域

一、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:请求的状态

  1. 0 - 未初始化,还没有调用send方法
  2. 1 - 载入,已调用send方法,正在发送
  3. 2 - 载入完成,send方法执行完成,已经接收到全部相应内容
  4. 3 - 交互,正在解析相应内容
  5. 4 - 完成,响应内容解析完成,可以在客户端调用

XMLHttpRequest.status:请求过程中的状态说明

  1. 2xx - 成功
  2. 1xx - 表示临时响应,客户端在收到常规响应时,应配置接收一个或多个1xx 响应
  3. 3xx - 表示重定向,客户端必须采取更多操作来实现请求。例如,浏览器不得不请求服务器上的不同的页面,或需要通过代理服务器重复该请求。如 304 表示可以使用缓存,该请求重复了
  4. 4xx - 表示客户端错误。例如,客户端请求不存在的页面,或客户端未提供有效的身份验证信息
  5. 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 等前端框架开发时,会发现它们在前后端分离的前提下,实现跨域请求的方式是在配置文件中添加代理。具体可以根据具体应用谷歌。

猜你喜欢

转载自blog.csdn.net/hoanFir/article/details/87933925