写在前面
- 看小伙伴写文章把 AJAX 当框架定义,和 Promise , axios 放到一起讲
- 个人感觉还是有些偏差的
- 这里分享一篇上学时的读书笔记
- 希望通过本文小伙伴们可以对 AJAX 有清晰的定义
- 博文内容主要为阅读 《Ajax基础教程》 整理笔记
时间决定你会在生命中遇到谁,你的心决定你想要谁出现在你的生命里,而你的行为决定最后谁能留下————《瓦尔登湖》
Web简史
Berners-lee 发明了 标准通用语言( Standard Generalized Markup language,SGML ) 的一个子集称为 超文本标记语言( HyperText Markup Language,HTML )
创建了称为 超文本传输协议( HyperText Transfer Protocol,HTTP ) 的简单协议,
还发明了第一个 Web浏览器 ,叫做 WorldWideWeb 。
Web发展例程:
最初的 Web页面 都是 静态 的,为了让 Web动态 ,引入的 CGI(Common Gateway Interfase,通用网关接口), 使用CGI在服务器端创建程序,CGI脚本可以使用多种语言编写。
对CGI的改进有了 applet , applet 允许开发人员编写可 嵌入在Web页面的小应用程序 ,在 浏览器的Java虚拟机(JVM) 中运行 applet
后来 Netscape 创建了一种动态脚本语言,最终命名为 JavaScript ,设计 JavaScript 是为了让 不太熟悉Java和Web 的开发人员能够更轻松的 开发applet ,Microsoft也推出了 VBScript
在 Java 出现一年以后, sun 引入 Servlet 即Java代码不用像 apple 那样的客户端浏览器中运行了,把它控制在一个应用服务器上运行,但是 servlet设计界面 很不方便,需要以 打印流 来输出,
为了将 表示与业务逻辑分离 ,出现了 JSP(JavaScript Pages) , Microsoft 也推出了 ASP 。用来设计页面
并不是只有 Microsoft 和 Sun 在努力寻找办法来 解决动态Web页面问题 。1996年夏天, FutureWave 发布了一个名叫 FutureSplash Animator的产品。这个产品起源于一个基于Java的动画*放播**器, FutureWave很快被Macromedia兼并,Macromedia则将这个产品改名为 Flash 。
Flash :利用flash可以发布高度交互的应用。
当 Microsoft 和 Netscape 发布其各自 浏览器的第4版 时,Web开发人员有了一个新的选择: 动态HTML (Dynamic HTML, DHTML) 。DHTML 不是 W3C 标准。
DHTML革命 :动态HTML(Dynamic HTML,DHTML) 结合HTML 层叠式样式表 (Cascading Style sheets, CSS ), JavaScript , DOM 。
Microsoft 对于交互式应用有一定了解,而且对于这种标准请求/响应模式的限制一直都不满意,因此提出了 远程脚本 ,但是 同步页面刷新 问题一直没有很好的解决方案。
Ajax 不只是一个特定的技术,更应算是一种技巧, JavaScript 是其主要组件。
Ajax 相关的术语就是 XMLHttpRequest 对象(XHR) ,它早在 IE5 (于1999年春天发布) 中就已经出现了,是作为 Active X 控件露面的。不过,最近出现的 新现象是浏览器的支持 。原先, XHR对象只在IE 中得到支持(因此限制了它的使用)
但是从 Mozilla 1.0 和 Safari 1.2 开始,对 XHR对象的支持开始普及 。这个很少使用的对象和相关的基本概念甚至已经出现在 W3C标准中 : DOM Level 3加载和保存规约(DOM Level 3 Load and Save Specification) 。特别是随着 Google Maps . Google Suggest , Gmail , Flickr , Netflix 和 A9 等应用变得越来越多手可热, XHR 也已经成为事实上的标准。
是谁发明了Ajax?
2005年2月, Adaptive Path 的 Jesse James Garrett 最早创造了这个词。在他的文章 Ajax:A New Approach to Web Applications (Ajax: Web应用的一种新方法) 中, Garrett 讨论了如何 消除胖客户(或桌面)应用与瘦客户(或Web)应用之间的界限。
当然,当 Google GoogleLabs 发布 Google Maps 和 Google Suggest 时,这个技术才真正为人所认识,而且此前已经有许多这方面的文章了。
但确实是Garrett最早提出了这个好名字,否则我们就得啰啰嗉嗉地说上大堆: 异步(Asynchronous)、 XMLHttpRequest、 JavaScript. CSS、DOM 等等 。
尽管原来把 Ajax 认为是 Asynchronous JavaScript + XML (异步 JavaScript + XML) 的缩写,但如今,这个词的覆盖面有所扩展,把允许浏览器与服务器通信而无需刷新当前页面的技术都涵盖在内
所以如何定义 AJAX :即 AJAX 是基于 XMLHttprequest对象(XHR),消除胖客户(桌面应用)与瘦客户(Web应用)应用之间的界线。通过 异步通信 ,允许浏览器与服务器通信而无需刷新当前页面的技术。
使用XMLHTTPrequest对象
使用XMLHttpRequest对象发送请求和处理响应之前,必须先写 JavaScript 创建一个 XMLHttpRequest 对象。
由于 XMLHttpRequest 并不是一个 W3C 标准,可以采用多种方法创建,Internet Explorer把XMLHttpRequest实现为一个ActiveXObject对象,其他浏览器把它实现为本地的Javascript对象。
var xmlHttp
function createXMLHttpRequest(){
if(window.ActiveXObject){ //IE浏览器
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){ //其他浏览器
xmlHttp = new XMLHttprequest();
}
}
方法和属性
|
方法属性 |
描述 |
|
void abort() |
停止当前请求 |
|
String getAllresponseHeadders() |
以字符串把HTTP请求的所有响应首部作为键值对返回 |
|
String getResponseheader("") |
返回指定首部字段的字符串 |
|
void open(string method,string url,boolean asynch,string username,string password) |
建立对服务器的调用,初始化请求的纯脚本方法,第三个参数表示调用为异步(true)还是同步(false),默认异步 |
|
void send(content) |
向服务器发出请求,如果声明异步,立即返回,否则等待接收到响应为之,可选参数可以是DOM对象的实例,输入流,或字符串,传入这个方法的内容会作为请求的一部分发送 |
|
void setRequestHeader(string header,string value) |
把指定的首部设置为所提供的值,在设置任何首部前必须先调用open()后才可调用 |
|
属性 |
描述 |
|
onreaddystatechange |
每个状态改变时都会触发这个事件处理器,通常会调用事件处理函数 |
|
readystate |
请求的状态,0(未初始化),1(正在加载),2(已加载),3(交互中),4(完成) |
|
responseText |
返回服务器的响应,表示为一个字符串 |
|
responseXML |
返回服务器的响应,表示为xml,可以解析为DOM对象 |
|
status |
服务器的HTTP状态码 |
|
statusText |
服务器状态码对应原因短语 |
交互实例
<input type = "text" id = "email" name ="email" onblur = "validateEmail()">
<script type = "text/Javascript">
var xmlHttp;
var email = document.getElementById("email");
var url = "validata?emali = "+escape(email.value);
//get方法数据作为URl一部分发送,地址数据?隔开。数据以键值对方式显示&隔开。
if(window.ActiveXObject){ //IE浏览器
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.XMLHttpRequest){ //其他浏览器
xmlHttp = new XMLHttprequest();
}
xmlHttp.open("GET",url);
xmlHttp.onreadystatechange = callback;
xmlHttp.send(null);
function callback(){
if(xmlHttp.readyState == 4 ){
if(xmlHttp.status ==200){
//do something interesting here
}
}
}
}
</script>
如何发送简单请求
使用 XMLHttprequest对象 发送请求的基本步骤:
- 得到XMLHttpRequest对象的实例引用,可以创建新实例,也可以访问已有的实例变量。
- 把对象的onreadystatechange属性设置为指向事件函数的指针。
- 指定请求的属性,open()方法
- 将请求发送给服务器,send()方法,如果没有数据作为请求体的一部分发送,使用null;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>simple XMLHttpRequest</title>
<script type="text/Javascript">
var xmlHttp;
function createXMlHttprequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveObject("Microsoft.XMLHttp");
}
else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}
function srartRequest(){
createXMLHttprequest();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET","simpleResponse.xml",true);
xmlHttp.send(null);
}
function handleStateChange(){
if(xmlHttp.readyState ==4){
if(xmlHttp.status == 200){
alert("The servlet replied with:"+xmlHttp.responseYext);
}
}
}
</script>
</head>
<body>
<form action="#">
<input type="button" value="Start Basic Asynchronous Request" onclick="startRequest()" />
</form>
</body>
</html>
与服务器通信
处理服务器响应: XMLHttpRequest对象提供responseText将响应提供为一个串 , responseXML 将响应提供为一个XML对象。
将响应解析为纯文本文件。
document.getElementBiId("idName").innerHTML = xmlHttp.responseText;
//以字符串的方式返回响应的内容,并写入到IDName中。
将响应 解析为XML文件:
要使服务器按XML格式响应数据,需要 Content_Type 首部为 text/xml ,当为纯文本时: text/piain
用于处理XML文档的DOM元素的属性方法
|
属性方法名 |
描述 |
|
childNodes |
返回文档元素所有子元素的数组 |
|
firstChild |
返回当前元素的第一个下级子元素 |
|
lastChild |
返回当前元素的最后一个子元素 |
|
nextsibling |
返回紧跟在当前元素后面的元素 |
|
nodeValue |
返回制定元素值得读/写属性 |
|
parentNode |
返回元素的父节点 |
|
previousSibling |
返回紧邻当前元素之前的元素 |
|
getElementById(document) |
获取有制定唯一属性值得文档中的元素 |
|
hasChildNodes() |
返回当前元素中指定标记名的子元素的数据 |
|
getAttirbut(name) |
返回元素的属性值,属性值由name指定 |
var XMLDoc= xmlHttp.responseXML;
//响应以XML格式返回。
发送请求参数:post方法将参数放到请求体中发送,get方法将讲参数追加到URL中发送。当使用post方法时,需要调用XMLHttpRequest对象的send()方法时发送字符串。
function doRequestUsingGET(){
createXMLHttpRequest();
var queryString = "请求地址?";
queryString = queryString + createQueryString() +"&timeStamp="+new Date().getTime();
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.open("GET","queryString",true);
xmlHttp.send(null);
}
function doRequestUsingPOST(){
carterXMLHttpRequest();//获取XMLHttp对象。
var url = "请求地址?timeStamp="+new Date().getTime();
var queryString = createQueryString();//获取参数字符串
xmlHttp.open("post",url,true);
xmlHttp.onreadystatechange = handleStateChange;//触发判断状态方法。
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded;");//确保服务器中知道请求体中有请求参数。
xmlHttp.send(quweyString);调用send()方法将查询串作为参数传递。
}
为什么要把时间戳追加到目标URl :有时浏览器会把多个XMLHttpRequest请求的结果缓存在同一个URL,如果对每个请求的响应不同,就会带来好的结果,把当前时间戳追加到YR来的最后,就能保证 URL的唯一性 。
请求参数作为XML发送
将请求参数以xml的格式作为请求体的一部分发送到服务器,与POST请求中将查询串作为请求体的一部分进行发送异曲同工,不同的是由XMLHttpRequest对象的send方法发送xml串。
结束标记中斜线前面的反斜线:xml = xml + “</pest>”;SGML规约中提供一个技巧,可以识别出script元素中的结束标记,但其他内容不能识别,使用反斜线可以避免把串解析为标记,根据严格的XHTML标准,应该使用反斜线。
在Java代码中,xml参数通过request对象获取,转换为字符流,字节流,通过 DocumentBuilderFactory对象方法转换为DOM对象,然后通过NodeList 对象解析获得数据。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
doGet(request, response);
String xml = readXMLFromRequestBody(request);
Document xmlDoc = null;
xmlDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new ByteArrayInputStream(xml.getBytes()));
}catch(ParserConfigurationException e) {
e.printStackTrace();
}catch(SAXException e) {
e.printStackTrace();
}
NodeList selectedPetTypes = xmlDoc.getElementsByTagName("type");
String type =null;
String responseText = "Selectsd Pets";
for(int i =0;i< selectedPetTypes.getLength();i++) {
type = selectedPetTypes.item(i).getFirstChild().getNodeValue();
responseText = responseText+" "+type;
}
response.setContentType("text/xml");
response.getWriter().print(responseText);
System.out.println(responseText);
}
private String readXMLFromRequestBody(HttpServletRequest request) {
StringBuffer xml = new StringBuffer();//实例化一个字符缓存区对象;
String line = null;
try {
BufferedReader reader = request.getReader();//请求字符缓存输入流,从字符输入流中读取文件,一次读取一行。
while((line =reader.readLine())!=null) {//循环读取一个文本行
xml.append(line);
}
}catch( Exception e) {
e.printStackTrace();
}
return xml.toString();
}
实现基本的Ajax技术
完成局部验证
function validate(){
createXMLHttpRequest();
var date = document.getElementById("birthDate");
var url = "ValidationServlet?birthDate=" + escape(date.value);
xmlHttp.open("GET",url,true);
xmlHttp.onreadystatechange = callback;
xmlHttp.send(null);
}
function callback(){
if(xmlHttp.readyState ==4){
if(xmlHttp.status == 200){
var mes = xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;
var val = xmlHttp.responseXML.getElementsByTagName("passed")[0].firstChild.data;
setMessage(mes,val);
}
}
}
function setMessage(message,isvalid){
var messageArea = document.getElementById("dateMessage");
var fontColor = "red";
if(isvalid == "true"){
fontColor = "green";
}
messageArea.innerHTML = "<font color = "+fontColor+">"+message+"</font>";
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
boolean passed = validateDate(request.getParameter("birthDate"));
response.setContentType("text/xml;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
String message = "You have entered an invalid date";
if(passed){
message ="You have entered an invalid date";
}
out.println("<response>");
out.println("<passed>"+Boolean.toString(passed)+"</passed>");
out.println("<message>"+message+"</message>");
out.println("</response>");
out.close();
}
private boolean validateDate(String date) {//判断字符串符合指定的日期格式
boolean isValid=true;
if(date!=null) {
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/YYYY");
try {
formatter.parse(date); //解析字符串的文本,生成 Date,
}catch(ParseException e) {
e.printStackTrace();
isValid=false;
}
}else {
isValid=false;
}
return isValid;
}
- 获取当前时间的的字符串格式。
- 读取响应首部
- 当服务器对HEAD请求做出响应时,它只发送响应首部忽略响应内容。
function handleStateChange(){
if(xmlHttp.readyState == 4){
if(requestType =="allResponseHeaders"){
getAllRequestHeaders();
}else if(requestType =="lastModified"){
getLastModified();
}else if(requestType =="isResourceAvailable"){
getIsResourceAvailable();
}
}
}
function getAllRequestHeaders(){
alert(xmlHttp.getAllResponseHeaders());
}
function getLastModified(){
alert("Last Modified:"+xmlHttp.getResponseHeader("Last-Modified"));
}
function getIsResourceAvailable(){
if(xmlHttp.status ==200){
alert("Successful^_^");
}else if(xmlHttp.status == 404){
alert("Resource is unavailable");
}else{
alert("Unexpected response status :"+xmlHttp.status);
}
Ajax 在开发中有很多的应用场景,比如下面的一些场景
- 动态加载列表框
- 创建自动刷新页面:
- 创建工具提示:
- 动态更新Web页面
jQuery对Ajax的实现:
通过 jQuery Ajax 方法,能够使数据 HTTP GET 或 HTTP POST 请求从远程服务器上请求文本, HTML,XML,JSON ,数据,同时能够把这些外部数据载入网页的被选元素中。
ajax() 方法:jQuery的底层实现, $.ajax() 方法返回其创建的 XMLHttpReuqst 对象,大多数无需操作该对象,特殊情况手动终止。只有一个参数:参数为key/value对象, $.ajax(options) 。参数可选。
$.ajax({
url:'/ExampleServlet',
type:'post',
dataType:'json',
success:function(data){alert('成功!');alert(data);},
error:function(){alert('内部错误');}
});
$.ajax({
async:false;
type:'post';
url:"example.jsp",
data:"name=Jfn&location=boss"
}).success(function(msg){alert("Data Saved:"+msg)
}).error(function(xmlHttpRequest,statusText,errorThrown){
alert("You form submission failed.\n\n"
+"XMLHttpRequest:"
+JSON.stringify(xmlHttpRequest)
+",\nStatusText:"+statusText
+",\nErroeThrown:"+errorThrown);
});
- load()方法从服务器加载数据,并把返回的数据放入被选元素:
- url:必须参数,指定需要加载的URL
- data:可选,规定与请求一同发送的查询字符串键/值对集合。
- callback:可选,请求成功完成的回调函数。
- get(),post():用于通过HTTP GET或POST请求从服务器请求数据,
- getJSON():通过HTTP GET 请求载入JSON数据,并尝试将其转为对应的JavaScript对象。
Promise 对象实现的 Ajax 操作
function ajax(URL) {
return new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', URL, true);
req.onload = function () {
if (req.status === 200) {
resolve(req.responseText);
} else {
reject(new Error(req.statusText));
}
};
req.onerror = function () {
reject(new Error(req.statusText));
};
req.send();
});
}
var URL = "/try/ajax/testpromise.php";
ajax(URL).then(function onFulfilled(value){
document.write('内容是:' + value);
}).catch(function onRejected(error){
document.write('错误:' + error);
});
关于AJAX和小伙伴们分享到这里