JavaScript奥秘之简述下你所知道的Ajax?

开发 前端
ajax全称:Asynchronous JavaScript and XML 即传说中的“异步JavaScript和XML”,他是由html、js、Dom等组成,这一杰出的技术可以将笨拙的web界面变成交互性的ajax应用程序。

前言

ajax已经流行很多年了,现在来说它是否已经晚了呢???特别是有这样框架那样框架后,还有几个人认识原生ajax呢?我们每天都会用到的东西你到底对他了解吗?

在最近一次面试上不幸被问到了,原以为很熟悉的东西你会发现你对他根本不熟悉!要说熟悉AJAX的话你需要毫不犹豫回答以下问题:

  1. 1 不同浏览器下ajax实现上的差异  
  2. 2 一次ajax请求过程中有哪几种状态值,不同状态值之间含义是什么3 ajax在跨域的情况下会出现什么状况,以及解决方案4 ajax和后台数据交互时会有什么编码问题吗?5 最后可以说说XMLHttpRequest2有什么新东西 

怎么样?各位能轻易的答上以上4点,便可直接忽略此文,若是只能很含糊的说出1、2点的话,便硬着头皮看我这篇水文吧,呵呵。

由于本文是边写边实验的,所以可能会有点乱,也可能会有我的唧唧歪歪的思考过程,请各位见谅。

另外,本人水平还很浅,写的东西必定有问题,若是文中有任何错误以及不足,请请一定指出来,多谢!

ajax简介

水文还是要有水文的样子,我这里还是需要简单介绍一番:

ajax全称:Asynchronous JavaScript and XML 即传说中的“异步JavaScript和XML”,他是由html、js、Dom等组成,这一杰出的技术可以将笨拙的web界面变成交互性的ajax应用程序。

ajax是一种构建网站的强大方法,他让我们桌面上只剩一个浏览器的想法不再是空谈,不再是妄想,虽说不大可能。。。

曾经我们的页面需要等待,等待服务器响应,等待屏幕刷新,等待请求返回和生成新页面。ajax的出现就让web页面的等待变得不那么明显,虽说只是感觉罢了(跟和美女在一起似的,感觉很爽)。。。

在一般的web应用程序中,用户提交表单后将整个表单发送到服务器,服务器将它转发给后台脚步(.net,java,php),脚步执行结束后将生成的新的htm页面返回,这个过程中就会出现我们前面所说的等待:屏幕变得一片空白,等待返回数据在重新绘制,这种交互性就跟你和一个美女XXOO每隔10秒才能动一下似的,这种感受,这种交互性怎一个差字了得???

ajax基本就是把js对象XMLHttpRequest对象放在web表单和服务器之间,当用户提交数据时只是将数据提交给js,然后由js发送给服务器并获取返回数据修改页面,过程中不会出现闪烁、消失或者延迟,传说中的异步请求。。。

XMLHttpRequest

该js对象为ajax的核心,前面说过了XmlHttpRequest是一套可以在Javascript脚本语言中通过http协议传送或接收XML及其他数据的一套API。XmlHttp最大的用处是可以更新网页的部分内容而不需要刷新整个页面。

首先我们来创建一个xml对象,需要注意兼容,我们先来个管中窥豹:

  1. 初始化   
  2.   <script type="text/javascript">  
  3.       var xmlHttp = false;  
  4.       if (window.XMLHttpRequest) {  
  5.           try {  
  6.               xmlHttp = new XMLHttpRequest();  
  7.           } catch (e) {  
  8.               xmlHttp = false;  
  9.           }  
  10.     } else {  
  11.           try {  
  12.               xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');  
  13.           } catch (e) {  
  14.               try {  
  15.                   xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');  
  16.               } catch (ee) {  
  17.                   xmlHttp = false;  
  18.               }  
  19.           }  
  20.       }  
  21.     
  22.       var s = '';  
  23.   </script> 

ajax的请求响应模型

ajax基本流程基本如下:

  1. 1 从web表单中获取所需数据(不用表单也行)  
  2. 2 建立连接url  
  3. 3 打开服务器连接  
  4. 4 设置数据返回回调函数  
  5. 5 发送请求 
  1. xmlHttp.open('GET', url, true);  
  2. xmlHttp.onreadystatechange = function (e) {};  
  3. xmlHttp.send(null) 

open时,最后一个参数为true将建立异步连接,false将等待服务器响应

onreadystatechage 可以指定数据返回时回调函数

send便是发送请求,参数便是要传的参数,没有参数可以填null

我们来写段后台程序试试:

  1. 前端   
  2.   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3.     
  4.   <html xmlns="http://www.w3.org/1999/xhtml">  
  5.   <head>  
  6.       <title></title>  
  7.   </head>  
  8.   <body>  
  9.     
  10.   </body>  
  11.   <script type="text/javascript">  
  12.       var xmlHttp = false;  
  13.       function createXMLHttpRequest() {  
  14.           if (window.XMLHttpRequest) {  
  15.               try {  
  16.                   xmlHttp = new XMLHttpRequest();  
  17.               } catch (e) {  
  18.                   xmlHttp = false;  
  19.               }  
  20.           } else {  
  21.               try {  
  22.                   xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');  
  23.               } catch (e) {  
  24.                   try {  
  25.                       xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');  
  26.                   } catch (ee) {  
  27.                       xmlHttp = false;  
  28.                   }  
  29.               }  
  30.           }  
  31.       }  
  32.     
  33.       createXMLHttpRequest();  
  34.       if (xmlHttp) {  
  35.           xmlHttp.open('GET''ajax.ashx'true);  
  36.           xmlHttp.onreadystatechange = function (e) {  
  37.               var tmp = xmlHttp.responseText;  
  38.               var s = '';  
  39.           }  
  40.           xmlHttp.send();  
  41.     
  42.       }  
  43.         
  44.     
  45.       var s = '';  
  46.   </script>  
  47.   </html> 
  1. 服务器端代码   
  2.  <%@ WebHandler Language="C#" Class="ajax" %>  
  3.    
  4.  using System;  
  5.  using System.Web;  
  6.    
  7.  public class ajax : IHttpHandler {  
  8.        
  9.      public void ProcessRequest (HttpContext context) {  
  10.          context.Response.ContentType = "text/plain";  
  11.          string name = context.Request.QueryString["name"] == null ? "" : context.Request.QueryString["name"].ToString();  
  12.          context.Response.Write("ajax 返回:" + name);  
  13.      }  
  14.     
  15.      public bool IsReusable {  
  16.          get {  
  17.              return false;  
  18.          }  
  19.      }  
  20.    
  21.  } 

其实我们定义的会函数会被执行三次,状态码依次返回2,3,4,现在我们来看看这个状态码是什么:

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

意思是我们只需要关注4便可以了。

另外几次请求返回数据一致可能是因为浏览器缓存原因,请各位自己加上随机数哟。

#p#

那些年我们一起跨的域

ajax也会遇到跨域问题的,我们所说的跨域现在一般都是跨域请求数据,跨域提交数据这种事情好像只有html5的postMessage能做。

跨域请求数据的原理是,我们先在我们的页面上定义一个js函数,然后以script的方式请求数据,数据返回的字符串便会调用我们定义的方法:

  1. xmlHttp.open('POST', 'http://localhost:47389/html5%E5%92%8Ccss3/ajax.ashx', true); 

将前面代码url处做一个修改后,请求就没有响应了,我们先看看这个url会输出什么:

  1. 跨域   
  2.  <%@ WebHandler Language="C#" Class="ajax" %>  
  3.    
  4.  using System;  
  5.  using System.Web;  
  6.    
  7.  public class ajax : IHttpHandler {  
  8.        
  9.      public void ProcessRequest (HttpContext context) {  
  10.          context.Response.ContentType = "text/plain";  
  11.          context.Response.Write("Hello World");  
  12.      }  
  13.     
  14.      public bool IsReusable {  
  15.          get {  
  16.              return false;  
  17.          }  
  18.      }  
  19.    
  20.  } 

[[71433]]

我们修改下后台代码:

  1. 修改后   
  2.  <%@ WebHandler Language="C#" Class="ajax" %>  
  3.    
  4.  using System;  
  5.  using System.Web;  
  6.    
  7.  public class ajax : IHttpHandler {  
  8.        
  9.      public void ProcessRequest (HttpContext context) {  
  10.          context.Response.ContentType = "text/html";  
  11.          string callback = context.Request.QueryString["callback"] == null ? "callback" : context.Request.QueryString["callback"].ToString();  
  12.          context.Response.Write(callback + "();");  
  13.      }  
  14.     
  15.      public bool IsReusable {  
  16.          get {  
  17.              return false;  
  18.          }  
  19.      }  
  20.    
  21.  } 

如此便会返回callback字符,

其实,说到异步跨域问题,我感觉就和ajax关系不大了,我想的是这样做:

  1. 跨域后台   
  2.  <%@ WebHandler Language="C#" Class="ajax" %>  
  3.    
  4.  using System;  
  5.  using System.Web;  
  6.    
  7.  public class ajax : IHttpHandler {  
  8.        
  9.      public void ProcessRequest (HttpContext context) {  
  10.          context.Response.ContentType = "text/html";  
  11.          string callback = context.Request.QueryString["callback"] == null ? "callback" : context.Request.QueryString["callback"].ToString();  
  12.          context.Response.Write(callback + "({name: '叶小钗'});");  
  13.      }  
  14.     
  15.      public bool IsReusable {  
  16.          get {  
  17.              return false;  
  18.          }  
  19.      }  
  20.    
  21.  } 
  1. 跨域前台   
  2.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3.    
  4.  <html xmlns="http://www.w3.org/1999/xhtml">  
  5.  <head>  
  6.      <title></title>  
  7.  </head>  
  8.  <body>  
  9.    
  10.  </body>  
  11.  <script type="text/javascript">  
  12.    
  13.      function callback() {  
  14.          alert('函数回调');  
  15.      }  
  16.      var url = 'http://localhost:47389/html5%E5%92%8Ccss3/ajax.ashx';  
  17.      var scpt = document.createElement('script');  
  18.      scpt.setAttribute('type''text/javascript');  
  19.      scpt.setAttribute('src', url);  
  20.      document.getElementsByTagName("head")[0].appendChild(scpt);  
  21.    
  22.  </script>  
  23.  </html> 

如此一来,便跨域了!

针对跨域post的处理,一般是以form target指向一个隐藏的iframe实现的,比如我们最初的文件图片上传“ajax”的实现。

编码问题

若是页面采用utf-8编码,而服务器采用gbk的话,也许会出现编码问题,甚至引起莫名其妙的BUG:

这里便让中文不能解析。

HTML5中的XMLHttpRequest

  1. 老版本缺点:  
  2. 只支持文本数据的传送,无法用来读取和上传二进制文件。  
  3. 传送和接收数据时,没有进度信息,只能提示有没有完成。  
  4. 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。 
  1. .0改进:  
  2. 可以设置HTTP请求的时限。  
  3. 可以使用FormData对象管理表单数据。  
  4. 可以上传文件。  
  5. 可以请求不同域名下的数据(跨域请求)。  
  6. 可以获取服务器端的二进制数据。  
  7. 可以获得数据传输的进度信息。 

作为XMLHttpRequest的改进版,IE9都还不支持呢,估计最新的IE10应该没问题了。

XMLHttpRequest Level2 在功能上有了很大的改进,比如2.0版本可以跨域啦!!!

跨域http请求包含一个origin头部,他为服务器提供http请求源信息,头部由浏览器保护,不能被程序更改,从本质上讲他与跨文档消息通信中消息事件的origin属性作用相同。

origin头部不同于早先的refer,后者referer是一个包含路径的完整url,路由可能包含敏感信息,浏览器不一定发送referer,但一定会发送origin。

算了,以上这块是抄的,我完全没有概念,反正意思是按照他的规则玩游戏,你就可以跨域!

我这里想要表达的重点其实是以下功能点:

XMLHttpRequest2.0支持了对进度的响应!确实是进度的响应,他让我们上传文件产生进度条变成了可能,之前仅有readystatechage一个事件能给用来响应进度,而且该事件并不兼容,如ie中就不会有状态3,更别说上传通信了,这种情况下要实现进度条是一件无比麻烦的事情:

我们来看看现在的事件列表

  1. loadStart  
  2. 传输开始时触发  
  3. progress  
  4. 上传过程中触发,他的e属性会包含很多有用信息哦。  
  5. abort  
  6. 取消上传时触发  
  7. error  
  8. 出错时触发  
  9. load  
  10. 接受完数据触发  
  11. loadend  
  12. 传输结束触发,无论成功与否 

若想查看例子请猛击: 一次上机面试题带来的感悟【学习的感觉、学习的方法】

此段参考资料:XMLHttpRequest Level 2 使用指南

结语

今天,我们一起学习了AJAX的相关知识,我感觉还是挺有用的。。。。若是有任何错误请指出哦。

责任编辑:张伟 来源: 博客园
相关推荐

2016-02-26 09:38:02

Ajax技术简述

2020-11-19 07:49:24

JS变量作用域

2023-06-26 08:24:23

JavaScriptAJAX

2017-01-15 11:38:24

2017-01-15 13:37:05

2016-12-26 16:58:37

2013-04-23 10:42:55

JavaScriptthis

2020-09-19 17:44:32

Linux计算器命令

2022-10-13 11:48:37

Web共享机制操作系统

2022-09-26 13:10:17

JavaScriptthis

2022-09-22 14:55:31

前端JavaScripthis

2011-04-19 13:32:01

jQueryjavascript

2018-11-28 11:20:09

区块链中本聪分布式

2022-03-10 08:25:27

JavaScrip变量作用域

2014-11-03 13:58:16

CSSWeb

2013-11-25 10:43:32

谷歌微软

2017-11-15 13:11:03

云计算Cloud TiDB技术

2023-07-07 14:47:46

JavaScript技巧

2021-01-28 10:04:40

JavaScript开发技术

2022-05-18 09:01:31

JavaScriptEvalErrorURIError
点赞
收藏

51CTO技术栈公众号