概述
Ajax(Asynchronous JavaScript and XML),AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
XMLHttpRequest
js中实现Ajax是基于XMLHttpRequest对象实现的,我们首先来看下如何使用XMLHttpRequest对象发起一个http请求。
发起一个请求
我们先回忆一下,一个完整的HTTP请求需要的是:
- 请求的网址、请求方法GET/POST。
- 提交请求的内容数据、请求主体等。
- 接收响应回来的内容。
使用XMLHttpRequest对象发起请求与之类似。
- 创建XMLHttpRequest对象
- 调用open方法设置请求内容
- 调用send方法发起请求
- 注册onreadystatechange事件
- 获取返回的数据。
下面我们先看个例程吧。
/*
* 使用XMLHttpRequest发起一个异步GET请求。
*/
// 实例化一个XMLHttpRequest对象
var xhr = new XMLHttpRequest();
// 调用open方法设置请求内容
xhr.open('get','https://lllhy.com',async=true);
// 调用send方法发起请求
xhr.send();
// 注册onreadystatechange事件
xhr.onreadystatechange = function(){
console.log(ajax.status);
console.log(ajax.readystate)
console.log('state change!')
}
相信你已经对XMLHttpRequest对象的使用已经有了一定的了解,接下来我们具体看看XMLHttpRequest吧。
详解
请求头
通过使用setRequestHeader
方法设置请求头,如
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
请求体
当发送POST请求时,调用send方法时可选择传入参数作为请求体。
xhr.send('name=fox&age=18');
相应状态
相信你再第一个例程中已经看到了。onreadystatechange事件并不只会在请求完成时触发,而是每次readystate状态变更时触发。
readystate状态有以下几种:
- 0:请求未初始化
- 1:服务器连接已建立
- 2:请求已接收
- 3:请求处理中
- 4:请求处理完成,相应已就绪
也就是只有当readystate为4时才表示相应已经就绪,所以我们在注册onreadystatechange事件时需要注意readystate是否为4
解析数据
我们最常接触到的相应数据有两种,JSON格式相应和XML相应,我们分别看下需要怎么解析这两种相应。
XML数据解析
我们可以通过responseXML查看相应的XML格式的数据。如下
var xhr = new XMLHttpRequest();
xhr.open('get','get_XMl.php');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status==200) {
// 如果 返回的是 xml文件
console.log(xhr.responseText);
// 异步 对象中 有另外一个属性 用来专门获取 xml
// xml对象 在浏览器段 就是一个 document对象
// 解析时 可以直接使用 querySelector 或者 getElementById等等 document对象 有的语法
console.log(xhr.responseXML);
console.log(xhr.responseXML.querySelector('kuzi').innerHTML);
// 下面这个 页面文档对象 如果要获取某个标签
console.log(window.document);
}
}
JSON数据解析
JSON数据解析时需要使用JSON.prase解析,并且需要将相应内容看作text读取,如下
var xhr = new XMLHttpRequest();
xhr.open('get','myJson.php');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState==4&&xhr.status==200) {
// json 字符串 是字符串 所以我们可以 通过 responseText获取
console.log(xhr.responseText);
// 转化为 js对象
var jsObj = JSON.parse(xhr.responseText);
console.log(jsObj);
}
}
手动实现JQuery中的Ajax方法
JQuery中的Ajax同样时基于XMLHttpRequest的,所以我们可以手工实现一个ajax方法。
大致思路为初始化请求参数,然后实例化XMLHttpRequest对象,使用XMLHttpRequest发送请求,最终对onreadystatechange中readystate进行判断,调用对应的回调函数。
function ajax(settings){
settings = initSettings(settings);
try{
var xhr = new XMLHttpRequest();
// 建立连接
xhr.open(settings.type,settings.url,settings.ansyc);
// beforeSend
settings.beforeSend(xhr);
// send
xhr.send(settings.data);
// onreadystatechange 事件
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
settings.complete(xhr, "success");
if(xhr.status != 200){
settings.error(xhr.status);
return;
}
// success
settings.success(xhr.responseText, xhr.responseXML);
}
}
}catch(e){
settings.error(e);
}
}
// 初始化请求参数
function initSettings(settings){
defaultSettings = {
type: "get",
url: "https://lllhy.com",
ansyc: true,
beforeSend: function(xhr){},
onreadystatechange: function(){},
complete: function(xhr, ts){},
contentType: "application/x-www-form-urlencoded",
context: settings,
data: {},
success: function(responseText,responseXML){},
error: function(e){console.log("request error: "+e);}
};
//使用settings更新defaultSettings
for(key in settings){
defaultSettings[key] = settings[key];
}
defaultSettings.data = formatParams(defaultSettings.data);
if(defaultSettings.type === "get"){
defaultSettings.url = defaultSettings.url+"?"+defaultSettings.data;
defaultSettings.data = null;
}
return defaultSettings;
}
// 格式化请求参数
function formatParams(data){
var arr=[];
for(var name in data){
arr.push(encodeURIComponent(name)+"="+encodeURIComponent(data[name]));
}
arr.push(("v="+Math.random()).replace(".",""));
return arr.join("&");
}
上面实现了一个非常简陋版本的Ajax方法。但是对于XMLHttpRequest对象以及ajax异步请求一定会有更深入的了解。
同源策略与跨域(CORS,Cross-origin resource sharing)
有的浏览器都遵守同源策略,这个策略能够保证一个源的动态脚本不能读取或操作其他源的http响应和cookie,这就使浏览器隔离了来自不同源的内容,防止它们互相操作。所谓同源是指协议、域名和端口都一致的情况。简单的来说,出于安全方面的考虑,页面中的JavaScript无法访问其他服务器上的数据,即“同源策略”。而跨域就是通过某些手段来绕过同源策略限制,实现不同服务器之间通信的效果。
跨域问题解决办法
跨域问题有两种解决办法:一种是通过CORS添加Access-Control-Allow-Origin的源站,并且在请求头中添加origin达到跨域请求的目的;还一种就是通过JSONP方式发起跨域请求。
JSONP
JSONP的主要思路如下:
由于AJAX不允许跨域请求,同时我们发现HTML标签中src不受跨域限制。如果我们通过<script>
的scr
属性设置我们需要访问的请求地址,同时将服务器返回设置为一行调用callback函数的JS语句。也就是将返回的数据传递给callback,由此我们就完美避开跨域问题且获取到了服务器的返回值。
看个例子:
<script type="text/javascript">
function callbackFunction(data){
//data内容就是服务器返回的数据
console.log(data);
}
// 通过JSONP的方式发起跨域请求
var url = "https://lllhy.com" + "?callback=callbackFunction";
var script = document.createElement("script");
script.setAttribute("src",url);
// 将标签加入dom
document.getElementsByTagName("head")[0].appendChild(script);
// 那么服务器端的返回应该如下,调用callback,并传入数据
callbackFunction({"data":"result data"})
<script>
服务器如果支持JSONP,那么最终会返回一个JS语句,来调用回调设置的回调函数,并且将服务器返回的数据作为参数,传递进去。
发表评论