JavaScript--20 深入理解 Ajax
深入学习 Ajax
- XMLHttpRequest 对象
- XHR的用法
- 同步请求
- 异步请求 - onreadystatechange 事件
- 进度事件
- 接收结束 - load事件
- 进度条 - progress事件
- 关于 HTTP 头部信息
- 修改请求头部信息
- 获取响应头部信息
- 请求类型
- GET 请求
- POST 请求
- FormData
Ajax 技术的核心是XMLHttpRequest 对象(简称XHR),XHR能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据。
虽然名字中包含XML 的成分,但Ajax 通信与数据格式无关;这种技术就是无须刷新页面即可从服务器取得数据,但不一定是XML 数据。
XMLHttpRequest 对象
IE7+
、Firefox
、Opera
、Chrome
和Safari
都支持原生的XHR
对象,可以像下面这样使用XMLHttpRequest
构造函数(IE7-
的版本这里就不写了)
var xhr = new XMLHttpRequest();
XHR的用法
在使用XHR
对象时,要调用的第一个方法是open()
,它接受3 个参数:
要发送的请求的类型("get"
、"post"
等)、请求的URL
和表示是否异步发送请求的布尔值(值为 false
时为同步请求)。
同步请求
xhr.open("get", "tet.json", false);
有关这行代码,需要说明两点:
一是URL
相对于执行代码的当前页面(当然也可以使用绝对路径);
二是调用open()方法
并不会真正发送请求,而只是启动一个请求以备发送。
要发送特定的请求,必须像下面这样调用send()方法
:
xhr.open("get", "tet.json", false);
xhr.send(null);
这里的send()方法
接收一个参数,即要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的。
调用send()之后,请求就会被分派到服务器。
由于这次请求是同步的,JavaScript 代码
会等到服务器响应之后再继续执行。在收到响应后,响应
的数据会自动填充XHR 对象的属性,相关的属性简介如下。
responseText:获得字符串形式的响应数据。
responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将获得 XML 形式的响应数据。对于非XML 数据而言,responseXML 属性的值将为null。
status:响应的HTTP 状态。
statusText:HTTP 状态的说明。
在接收到响应后,第一步是检查status 属性
,以确定响应已经成功返回。
一般来说,可以将HTTP状态代码
为200
作为成功的标志。此时,responseText 属性
的内容已经就绪。此外,状态代码
为304
表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本,也意味着响应是有效的。为确保接收到适当的响应,应该像下面这样检查上述这两种状态代码:
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log(xhr,'\n'+xhr.response);
} else {console.log("请求错误: " + xhr.status);
}
所以一个完整的同步请求代码如下:
var xhr = new XMLHttpRequest();
xhr.open('get','./test.json',false);
xhr.send(null);if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log(xhr,'\n'+xhr.response);
} else {console.log("请求错误: " + xhr.status);
}
异步请求 - onreadystatechange 事件
xhr.open("get", "tet.json", true);
open() 方法
的第三个参数为 true
时,执行的是异步请求,多数情况下,我们还是要发送异步请求,才能让 JavaScript
继续执行而不必等待响应。此时,可以检测XHR 对象
的readyState 属性
,该属性表示请求/响应过程的当前活动阶段。这个属性可取的值如下。
0:未初始化。尚未调用open()方法。
1:启动。已经调用open()方法,但尚未调用send()方法。
2:发送。已经调用send()方法,但尚未接收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
只要readyState 属性
的值由一个值变成另一个值,都会触发一次readystatechange 事件
。可以利用这个事件来检测每次状态变化后readyState
的值。通常,我们只对readyState
值为4
的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用open()
之前指定onreadystatechange事件
处理程序才能确保跨浏览器兼容性。下面来看一下异步请求的写法:
var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){console.log(xhr.readyState);if (xhr.readyState == 4){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log(xhr,'\n'+xhr.responseText);} else {console.log("请求错误: " + xhr.status);}}
};xhr.open('get','./test.json',true);
xhr.send(null);
以上代码利用DOM 0 级方法为XHR 对象添加了事件处理程序,原因是并非所有浏览器都支持DOM 2级方法。与其他事件处理程序不同,这里没有向onreadystatechange
事件处理程序中传递event
对象;必须通过XHR 对象本身来确定下一步该怎么做。
另外,在接收到响应之前还可以调用abort()
方法来取消异步请求,如下所示:
xhr.abort();
调用这个方法后,XHR 对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。
进度事件
接收结束 - load事件
有以下6 个进度事件。
loadstart:在接收到响应数据的第一个字节时触发。
progress:在接收响应期间持续不断地触发。
error:在请求发生错误时触发。
abort:在因为调用abort()方法而终止连接时触发。
load:在接收到完整的响应数据时触发。
loadend:在通信完成或者触发error、abort 或load 事件后触发。
每个请求都从触发loadstart 事件
开始,接下来是一或多个progress 事件
,然后触发error
、abort
或load 事件
中的一个,最后以触发loadend 事件
结束。
支持前5 个事件的浏览器有Firefox 3.5+、Safari 4+、Chrome、iOS 版Safari 和Android 版WebKit
。Opera(从第11 版开始)
、IE 8+
只支持load 事件
。目前还没有浏览器支持loadend 事件
。
所以这里只介绍一下 load 事件
和 progress事件
load 事件
可用以替代readystatechange 事件
。响应接收完毕后将触发load 事件
,因此也就没有必要去检查readyState 属性
了。
var xhr = new XMLHttpRequest();
xhr.onload = function(){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log(xhr,'\n'+xhr.responseText);} else {console.log("请求错误: " + xhr.status);}
};
xhr.open("get", "./test.json", true);
xhr.send(null);
进度条 - progress事件
progress 事件
会在浏览器接收新数据期间周期性地触发。而onprogress 事件
处理程序会接收到一个event 对象
,其target 属性
是XHR 对象
。下面展示了为用户创建进度指示器的一个示例。
为确保正常执行,必须在调用open()方法
之前添加onprogress 事件
处理程序。
var xhr = new XMLHttpRequest();
xhr.onprogress = function(event){if (event.lengthComputable){console.log(event)}
};
xhr.open("get", "./test.json", true);
xhr.send(null);
上图中包含了总数,请求过程中已请求的数据,打印时候的时间等信息,根据这些信息可以轻易地实现进度条效果。
关于 HTTP 头部信息
每个HTTP
请求和响应都会带有相应的头部信息,其中有的对开发人员有用,有的也没有什么用。
XHR 对象
也提供了操作这两种头部(即请求头部
和响应头部
)信息的方法。
修改请求头部信息
默认情况下,在发送XHR 请求
的同时,还会发送下列头部信息。
Accept:浏览器能够处理的内容类型。
Accept-Charset:浏览器能够显示的字符集。
Accept-Encoding:浏览器能够处理的压缩编码。
Accept-Language:浏览器当前设置的语言。
Connection:浏览器与服务器之间连接的类型。
Cookie:当前页面设置的任何Cookie。
Host:发出请求的页面所在的域 。
Referer:发出请求的页面的URI。
User-Agent:浏览器的用户代理字符串。
虽然不同浏览器实际发送的头部信息会有所不同,但以上列出的基本上是所有浏览器都会发送的。
使用setRequestHeader()方法
可以设置自定义的请求头部信息。
这个方法接受两个参数:头部字段的名称和头部字段的值。
要成功发送请求头部信息,必须在调用open()方法
之后且调用send()方法
之前调用setRequestHeader()
,如下面的例子所示:
var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){console.log(xhr.readyState);if (xhr.readyState == 4){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log(xhr,'\n'+xhr.responseText);} else {console.log("请求错误: " + xhr.status);}}
};xhr.open('get','./test.json',true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);
服务器在接收到这种自定义的头部信息之后,可以执行相应的后续操作。我们建议读者使用自定义的头部字段名称,不要使用浏览器正常发送的字段名称,否则有可能会影响服务器的响应。有的浏览器允许开发人员重写默认的头部信息,但有的浏览器则不允许这样做。
获取响应头部信息
调用XHR 对象
的getResponseHeader()方法
并传入头部字段名称,可以取得相应的响应头部信息。而调用getAllResponseHeaders()方法
则可以取得一个包含所有头部信息的长字符串。来看下面的例子。
var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if (xhr.readyState == 4){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){var contentType = xhr.getResponseHeader("content-type");var allHeaders = xhr.getAllResponseHeaders();console.log(contentType+'\n\n',allHeaders);} else {console.log("请求错误: " + xhr.status);}}
};xhr.open('get','./test.json',true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);
请求类型
GET 请求
GET
是最常见的请求类型,最常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL
的末尾,以便将信息发送给服务器。对XHR
而言,位于传入open()方法
的URL 末尾
的查询字符串必须经过正确的编码才行。
使用GET 请求经常会发生的一个错误,就是查询字符串的格式有问题。查询字符串中每个参数的名称和值都必须使用encodeURIComponent()
进行编码,然后才能放到URL 的末尾;而且所有名-值对
儿都必须由和号(&)
分隔,如下面的例子所示。
xhr.open("get", "./test.json?name1=value1&name2=value2", true);
下面这个函数可以辅助向现有URL 的末尾添加查询字符串参数:
function addURLParam(url, name, value) {url += (url.indexOf("?") == -1 ? "?" : "&");url += encodeURIComponent(name) + "=" + encodeURIComponent(value);return url;
}
//下面是使用这个函数来构建请求URL 的示例。
var url = "./test.json";
//添加参数
url = addURLParam(url, "name", "RunSky87");
url = addURLParam(url, "age", 24);
//初始化请求
xhr.open("get", url, true);
这个addURLParam()函数
接受三个参数:要添加参数的URL、参数的名称和参数的值。这个函数
首先检查URL 是否包含问号(以确定是否已经有参数存在)。如果没有,就添加一个问号;否则,就添
加一个和号。然后,将参数名称和值进行编码,再添加到URL 的末尾。最后返回添加参数之后的URL。
在上面的例子中,您可能得到的是缓存的结果。可以向 URL 添加一个唯一的 ID 解决这个问题:
xhr.open("get", "./test.json?name1=value1&name2=value2&t=" + Math.random(), true);
POST 请求
POST 请求通常用于向服务器发送应该被保存的数据。POST 请求的主体可以包含非常多的数据,而且格式不限。在open()方法第一个参数的位置传入"post",就可以初始化一个POST 请求,如下面的例子所示。
xhr.open("post", "./test.json", true);
发送POST
请求的第二步就是向send()方法
中传入某些数据。由于XHR
最初的设计主要是为了处理XML
,因此可以在此传入XML DOM 文档
,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串。
默认情况下,服务器对POST 请求
和提交Web 表单
的请求并不会一视同仁。因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。
不过,我们可以使用XHR
来模仿表单提交:首先将Content-Type
头部信息设置为application/x-www-form-urlencoded
,也就是表单提交时的内容类型,其次是以适当的格式创建一个字符串。这里如果不设置Content-Type
头部信息,服务器想要获取数据就要做一些操作。
<form id="input" name="input" action="{{请求的url}}" method="post">Username: <input type="text" name="username" value="admin">Password: <input type="password" name="password" value="111111"><input type="submit" value="Submit">
</form>
下面的写法可以模仿上面的表单提交:
var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if (xhr.readyState == 4){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log("请求成功");} else {console.log("请求错误: " + xhr.status);}}
};xhr.open('post','{{请求的url}}',true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send('username=admin&password=111111');
FormData
说到这里就不得不提一下 FormData 对象。
FormData
为序列化表单以及创建与表单格式相同的数据(用于通过XHR 传输)提供了便利。下面的代码创建了一个FormData 对象
,并向其中添加了一些数据。
使用FormData
的方便之处体现在不必明确地在XHR 对象上设置请求头部。XHR 对象能够识别传入的数据类型是FormData
的实例,并配置适当的头部信息。
var data = new FormData();
data.append("username", "admin");
这个append()方法
接收两个参数:键
和值
,分别对应表单字段的名字和字段中包含的值。可以像这样添加任意多个键值对儿。而通过向FormData 构造函数
中传入表单元素,也可以用表单元素的数据预先向其中填入键值对儿:
var data = new FormData(document.forms[0]);
创建了FormData
的实例后,可以将它直接传给XHR 的send()方法
,,上面的 POST
可以写成下面的形式:
var xhr = new XMLHttpRequest();xhr.onreadystatechange = function(){if (xhr.readyState == 4){if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){console.log("请求成功");} else {console.log("请求错误: " + xhr.status);}}
};var data= new FormData();
data.append("username", "admin");
data.append("password", "111111");
xhr.open('post','{{请求的url}}',true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
JavaScript--20 深入理解 Ajax相关推荐
- 回调函数举例ajax,通过回调函数的理解来进一步理解ajax及其注意的用法
一,再一次理解回调函数 (function($){ $.fn.shadow = function(opts){ //定义的默认的参数 var defaults = { copies: 5, opaci ...
- 我对javascript对象的理解
前言 JavaScript这门语言除了基本类型都是对象,可以说JavaScript核心就是对象,因此理解JavaScript对象及其种种特性至关重要,这是内功.本文介绍了我对es5对象,原型, 原型链 ...
- java中使用ajax请求数据格式,Java基本数据类型 javascript中post和ajax提交 Axure
Java基本数据类型 Java一共有八种基本类型,六种数据类型,一种字符类型,一种布尔类型 分别是 byte 是数据类型内存大小1,内存位数是8位,最小值是-128(-27),最大值:127(27-1 ...
- javascript之异步操作理解---回调函数,async,await以及promise对象
javascript之异步操作理解---回调函数,async,await以及promise对象 概述 概述 写在前面:虽然平时做项目,但是发现自己写的代码还是很烂.最近接触了一个对性能要求比较高的项目 ...
- 【javascript】深入理解对象
为什么80%的码农都做不了架构师?>>> 今天学习的主题是 JavaScript对象. 要创建一个JavaScript对象大家应该都觉得很简单,直接写上一行 var obj = ...
- JavaScript面向对象——深入理解寄生组合继承
JavaScript面向对象--深入理解寄生组合继承 之前谈到过组合继承,会有初始化两次实例方法/属性的缺点,接下来我们谈谈为了避免这种缺点的寄生组合继承 寄生组合继承: 思路:组合继承中,构造函数继 ...
- JavaScript面向对象——深入理解原型继承
JavaScript继承--深入理解原型继承 原型继承 // 父类function School (name, address) {this.name = namethis.address = add ...
- 【Javascript】深入理解this作用域问题以及new/let/var/const对this作用域的影响
理解this作用域 <javascript高级程序设计>中有说到: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象调用时,t ...
- Javascript闭包简单理解
Javascript闭包简单理解 原文:Javascript闭包简单理解 提到闭包,想必大家都早有耳闻,下面说下我的简单理解. 说实话平时工作中实际手动写闭包的场景并不多,但是项目中用到的第三方框架和 ...
- JavaScript之全面理解面向对象的JS
今天看到一篇文章写得很好,对于像博主这种js一般级别的菜鸟很有帮助,博主秉着"好文要转"的原则收藏了这篇文章,简单排了下版,分享给大家,本文转自原文:http://www.ibm. ...
最新文章
- 高中生也能读懂的Docker入门教程
- sshpass连接主机以及执行命令
- Reference和ReferenceQueue
- 自动化部署脚本开启所有zookpeer等服务
- SpringCloud Ribbon实战以及Ribbon随机策略RandomRule的源码浅析(六)
- poatman32位下载_Postman.dll下载|Postman.dll下载官方版【32位|64位】-太平洋下载中心...
- Smarty 获取当前日期时间和格式化日期时间
- moba的m是什么意思_moba游戏是什么
- Sqlite加密问题
- sharepoint搭建文档服务器,SharePoint Server教程
- SQL获取当天0点0分0秒和23点59分59秒方法
- MSP430第三十二章:Comp_B
- idea报错 Result Maps collection does not contain value for com.
- 影视后期制作课题报告
- (转载)使用Android Studio对代码进行重构
- ES6对数组进行正序和倒序排列
- 硬核:如何用「区块链」改进传染病监测预警网络?
- C++边边角角(一)
- redmine2.0 + mongrel
- 【心得体会】2022年华为杯数学建模比赛参赛心得体会