时间决定你会在生命中遇到谁,你的心决定你想要谁出现在你的生命里,而你的行为决定最后谁能留下————《瓦尔登湖》
写在前面
看小伙伴写文章把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对象。
1 2 3 4 5 6 7 8 var xmlHttpfunction createXMLHttpRequest ( ) { if (window .ActiveXObject){ 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
服务器状态码对应原因短语
交互实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <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);if (window .ActiveXObject){ 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 ){ } } } } </script >
如何发送简单请求 使用XMLHttprequest对象发送请求的基本步骤:
得到XMLHttpRequest对象的实例引用,可以创建新实例,也可以访问已有的实例变量。
把对象的onreadystatechange属性设置为指向事件函数的指针。
指定请求的属性,open()方法
将请求发送给服务器,send()方法,如果没有数据作为请求体的一部分发送,使用null;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <!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对象。
将响应解析为纯文本文件。
1 2 document .getElementBiId("idName" ).innerHTML = xmlHttp.responseText;
将响应 解析为XML文件:
要使服务器按XML格式响应数据,需要Content_Type首部为text/xml,当为纯文本时:text/piain
用于处理XML文档的DOM元素的属性方法
属性方法名
描述
childNodes
返回文档元素所有子元素的数组
firstChild
返回当前元素的第一个下级子元素
lastChild
返回当前元素的最后一个子元素
nextsibling
返回紧跟在当前元素后面的元素
nodeValue
返回制定元素值得读/写属性
parentNode
返回元素的父节点
previousSibling
返回紧邻当前元素之前的元素
getElementById(document)
获取有制定唯一属性值得文档中的元素
hasChildNodes()
返回当前元素中指定标记名的子元素的数据
getAttirbut(name)
返回元素的属性值,属性值由name指定
1 2 var XMLDoc= xmlHttp.responseXML;
发送请求参数: post方法将参数放到请求体中发送,get方法将讲参数追加到URL中发送。当使用post方法时,需要调用XMLHttpRequest对象的send()方法时发送字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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(); 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 对象解析获得数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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技术 完成局部验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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>" ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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); }catch (ParseException e) { e.printStackTrace(); isValid=false ; } }else { isValid=false ; } return isValid; }
获取当前时间的的字符串格式。
读取响应首部
当服务器对HEAD请求做出响应时,它只发送响应首部忽略响应内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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)。参数可选。
1 2 3 4 5 6 7 $.ajax({ url :'/ExampleServlet' , type :'post' , dataType :'json' , success :function (data ) {alert('成功!' );alert(data);}, error :function ( ) {alert('内部错误' );} });
1 2 3 4 5 6 7 8 9 10 11 12 13 $.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 操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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和小伙伴们分享到这里