Ajax知识整理

先引入一下HTTP的请求过程还有介绍一下运行环境

一个完整的HTTP请求过程,通常有下面7个步骤:

  建立TCP连接
  Web浏览器向Web服务器发送请求命令
  Web浏览器发送请求头信息
  Web服务器- 应答
  Web服务器- 发送应答头信息
  Web服务器- 向浏览器发送数据
  Web服务器- 关闭TCP连接

Ajax必须在服务器环境下才能正常使用:

  可以使用WampServer程序

AJAX简介

Ajax(Asynchronous JavaScript and XML 异步的JavaScript与XML)是一种与服务器交换数据无需刷新网页的技术,最早由Google公司在谷歌地图里使用,并迅速风靡。

它是一系列web开发技术的集合,是一种使用很多的web技术,能在在客户端开发异步web应用。利用Ajax,web应用可以异步的发送数据获取数据,而不干扰现有页面的显示和行为。通过解耦数据接口层和展现层,Ajax允许web页面或者其他扩展的web应用动态的改变数据而不用重新加载整个页面。实现通常选择JSON代替XML,因为JSON更接近JavaScript,操作更加方便。

Ajax不是一种技术,是一组技术。HTML和CSS用来组合标记和样式信息。用户可以利用js访问DOM对象负责动态展示。js和XMLHttpRequest对象提供一种浏览器和服务端异步互换数据的方法从而避免整个页面加载。

关于AJAX的历史

在90年代中期,许多web站点完全基于html页面。每个用户行为都需要从服务端重新加载页面。这个过程很不方便,影响用户体验:所有的页面内容消失,然后又出现。每次因为小部分改动需要浏览器重新加载页面,所有内容都必须重新获取,甚至只有很少的信息改变。这会额外增加服务端负载,浪费带宽,影响性能。

在1996年,IE引入了iframe标签来异步加载获取内容。

在1998年,微软的邮件组团队利用客户端脚本实现了第一个XMLHTTP组件。

在1999年,微软在IE的默认页面使用iframe技术动态更新新闻故事和股票行情,并且在IE5中创建了XMLHTTP ActiveX组件,这个技术随后被Mozilla,Safari,Opera以及其他浏览器采用,作为XMLHttpRequest js对象。微软在IE7中采用了原生的XMLHttpRequest模块。IE仍然支持ActiveX版本,但是在Edge中不支持了。这种技术的使用在当时相当不明朗直到出现在大规模线上应用中,比如Outlook Web App (2000)和Oddpost。

谷歌在Gmail(2004)和Google Maps(2005)中广发部署了符合标准的跨浏览器Ajax。在2004年10月Kayak.com的公测版本是首次大规模电子商务网站使用了他们当时称为"the xml htpp thing"的技术。

Jesse James Garrett在2005年2月18号发表的一篇题为"Ajax: A New Approach to Web Applications"的论文中,基于Google 页面中使用的技术,公开阐明了"Ajax"这个术语。

在2006年4月5号,W3C发表了第一个关于XMLHttpRequest对象的草案,尝试建立一个官方的Web标准。关于XMLHttpRequest对象最新的草案是在2014年1月30号发布的。

技术集

Ajax术语已经变成了web应用用来与服务端在幕后交流不打断页面当前状态而使用的一组技术的代表。在Jesse James Garrett的论文里创造的Ajax术语包括以下技术:

  展现层的HTML(或者XHTML)和CSS
  动态显示和与数据交互的DOM对象
  为了交换数据的JOSN或者XML,为了操纵数据的XSLT
  为了异步通信的XMLHttpRequest对象
  把这些技术整合起来的JavaScript

工作原理

传统Web应用模型与使用Ajax的Web应用模型对比

传统方式: 客户端发起请求--等待-->服务器端处理---等待-->响应-->页面载入 (请求错误时全部重新载入).

使用AJAX: 客户端发起请求--->服务器端处理--->响应--->页面载入(填写时,即时更新,部分返回).

编写AJAX

所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。

Ajax编写步骤

  1.创建Ajax对象
  2.连接服务器
  3.发送请求
  4.接受返回

创建Ajax对象:

//IE6以上
var oAjax = new XMLHttpRequest();

//IE6
var oAjax =new ActiveXObject("Microsoft.XMLHTTP")

连接服务器

open(method,url,async);

open(发送请求方法"GET/POST" ,(请求地址"文件名") ,是否异步传输)
例: request.open("GET","get.json",true);

Ajax天生就是工作在异步模式的(异步为true,同步false)

同步和异步

同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。 
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。 

发送请求send()

send(string)
在使用GET方式请求时无需填写参数
在使用POST方式时参数代表着向服务器发送的数据

//完整的GET请求
var oAjax = new XMLHttpRequest();//创建Ajax对象
oAjax.open("GET","create.php",true);//连接服务器
oAjax.send();//发送请求

//完整的POST发送请求
var oAjax = new XMLHttpRequest();//创建
oAjax.open("POST","create.php",true);//"POST"
oAjax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");//设置HTTP头信息.必须在open与send之间,否则出现异常.
oAjax.send("name=陈二狗&sex=男");//发送给服务器的内容

GET 还是 POST?
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

然而,在以下情况中,请使用 POST 请求:
  无法使用缓存文件(更新服务器上的文件或数据库)
  向服务器发送大量数据(POST 没有数据量限制)
  发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

接收返回信息

oAjax.onreadystatechange = function(){   //当请求状态改变时要调用的事件处理器
    alert(oAjax.readystate);           
}

只要readyState属性的值发生变化时,便会触发一次readyStatechange事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们只对readyState值为4的阶段感兴趣,因为这时所有数据都已经就绪,不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。

下面来看一个例子:

var xhr = createXHR();
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
            alert(xhr.statusText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};
xhr.open("get", "example.txt", true);
xhr.send(null);

XMLHttpRequest这个对象的属性:

onreadystatechange  每次状态改变所触发事件的事件处理程序。

responseText     从服务器进程返回数据的字符串形式。
responseXML    从服务器进程返回的DOM兼容的文档数据对象。

status           从服务器返回的数字代码,比如常见的404(未找到)和200(已就绪)

status Text       伴随状态码的字符串信息

当XHR对象把一个HTTP请求发送到服务器的过程中会经历几个状态,直到请求被处理,然后才接收一个回应。readyState就是XHR请求的状态属性,它本身有5个属性值:

0(未初始化)还没有调用open()方法
1(载入)已调用send()方法,正在发送请求
2(载入完成)send()方法完成,已收到全部响应内容
3(解析)正在解析响应内容
4(完成)响应内容解析完成,可以再客户端使用了

status和statusText

statusText是响应返回的文本信息,仅当readyState值为3或4的时候才能使用。当readyState为其它值时视图存取statusText属性将引发异常。

XHR的方法

方法描述
abort() 导致当前正在执行的请求被取消
getAllResponseHeaders() 返回包含所有响应头的名称和值的单个字符
getResponseHeader(name) 返回响应头中指定的名称和值
open(method,url,async,username,pwd) 设置HTTP方法(get或post)等
send(content) 发出带有指定主体内容的请求
setRequestHeader(name,value) 使用指定的名称和值设置请求头
//基本完整的一个Ajax请求
var request = new XMLHttpRequest();
request.open("GET","get.json",true);
request.onreadystatechange = function () {
    if (request.readyState === 4) {
        if (request.status === 200) {
            //响应成功,做一些事情
        } else {
           //响应失败,做一些事情
        }
    }
};

使用函数简单的封装一个get请求

/**
 * 一个简单的异步get请求
 * @param {String}   url     请求地址,文件名
 * @param {Function} fnSucc  请求成功时执行的函数,形参为为获取的字符串值.
 * @param {Function} fnFaild 请求失败执行的函数,可选参数
 */
function get(url, fnSucc, fnFaild) {
    //1.创建ajax对象
    var oAjax = null
        //此处必须需要使用window.的方式,表示为window对象的一个属性.不存在是值为undefined,进入else/若直接使用XMLHttpRequest在不支持的情况下会报错
    if (window.XMLHttpRequest) {
        oAjax = new XMLHttpRequest();
    } else {
        //IE6以上,现在应该不需要考虑IE6了
        oAjax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2.连接服务器
    //open(方法,url,是否异步)
    oAjax.open("GET", url, true);
    //3.发送请求
    oAjax.send();
    //4.接收返回
    //OnRedayStateChange事件
    oAjax.onreadystatechange = function () {
        if (oAjax.readyState === 4) {
            if (oAjax.status === 200) {
                fnSucc(oAjax.responseText);
            } else {
                if (fnFaild) {
                    fnFaild();
                }
            }
        }
    };
}

这样的封装还不够,原因如下:

  目前方法只能使用get请求,而不能使用post请求,而在用户注册时必须使用POST,因为POST,现在不够完整。
  目前请求参数只能直接写在url里,不利于动态获取数据,应该使用参数解析的方式,便于使用。
  get请求方式请求缓存问题。

封装如下:

/**
 * AJAX函数封装
 * @param {string} url     请求地址(必须)
 * @param {object} options 发送请求的选项参数
 * @config {string} [options.type] 请求发送的类型。默认为GET。
 * @config {Object} [options.data] 需要发送的数据。
 * @config {Function} [options.onsuccess] 请求成功时触发,function(oAjax.responseText, oAjax)。(必须)
 * @config {Function} [options.onfail] 请求失败时触发,function(oAjax)。(oAJax为XMLHttpRequest对象)
 *
 *@returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
 */
function AJAX(url, options) {
    //1.创建ajax对象
    var oAjax = null;
        /**
         * 此处必须需要使用window.的方式,表示为window对象的一个属性.不存在时值为undefined,进入else
         * 若直接使用XMLHttpRequest,在不支持的情况下会报错
         **/
    if (window.XMLHttpRequest) {
        //IE6以上
        oAjax = new XMLHttpRequest();
    } else {
        oAjax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    
    //2.连接服务器
    //open(方法,url,是否异步)
    var param = ""; //请求参数。
    //只有data存在,且为对象使才执行
    var data = options.data ? options.data : -1; //缓存data
    if (typeof (data) === "object") {
        for (var key in data) { //请求参数拼接
            if (data.hasOwnProperty(key)) {
                param += key + "=" + data[key] + "&";
            }
        }
        param.replace(/&$/, "");
    } else {
        param = "timestamp=" + new Date().getTime();
    }

    //3.发送请求
    var type = options.type ? options.type.toUpperCase() : "GET";
    if (type === "GET") {
        oAjax.open("GET", url + "?" + param, true);
        oAjax.send();
    } else {
        oAjax.open("POST", url, true);
        oAjax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        oAjax.send(param);
    }

    //4.接收返回
    //OnRedayStateChange事件
    oAjax.onreadystatechange = function () {
        if (oAjax.readyState === 4) {
            if (oAjax.status === 200) {
                //请求成功。形参为获取到的字符串形式的响应数据
                options.onsuccess(oAjax.responseText, oAjax);
            } else {
                //先判断是否存在请求失败函数
                //存在时,形参为XMLHttpRequest对象,便于进行错误进行处理
                if (options.onfail) {
                    options.onfail(oAjax);
                }
            }
        }
    };
    return oAjax;//发送请求的XMLHttpRequest对象
}

options是一个对象,里面可以包括的参数为:

  type: post或者get,可以有一个默认值
  data: 发送的数据,为一个键值对象或者为一个用&连接的赋值字符串
  onsuccess: 成功时的调用函数
  onfail: 失败时的调用函数

应用优势

· AJAX不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
· 使用Javascript向服务器提出请求并处理响应而不阻塞用户!核心对象XMLHTTPRequest。通过这个对象,您的 JavaScript 可在不重载页面的情况与Web服务器交换数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果。
· AJAX 在浏览器与 Web 服务器之间使用异步数据传输(HTTP 请求),这样就可使网页从服务器请求少量的信息,而不是整个页面。
· AJAX 可使因特网应用程序更小、更快,更友好。
· AJAX 是一种独立于 Web 服务器软件的浏览器技术。 

· AJAX 基于下列 Web 标准:
JavaScriptXMLHTMLCSS在 AJAX 中使用的 Web 标准已被良好定义,并被所有的主流浏览器支持。AJAX 应用程序独立于浏览器和平台。
Web 应用程序较桌面应用程序有诸多优势;它们能够涉及广大的用户,它们更易安装及维护,也更易开发。
不过,因特网应用程序并不像传统的桌面应用程序那样完善且友好。
通过 AJAX,因特网应用程序可以变得更完善,更友好。

弊端

· 如果用户浏览器不支持JavaScript或者XMLHttpRequest,或者禁用这种功能,则不能正常使用依赖Ajax的页面。简单设备(例如智能手机,pad)可能不支持需要的这些技术。让用户使用这种功能的唯一方法是回退到没有JavaScript方法。可以同通过确保链接表单正确解析而不是仅仅依赖Ajax来实现相关功能。
· 同样的,一些使用Ajax的Web应用对屏幕阅读技术不友好,例如JAWS。WAI-ARIA标准提供了一种方法在这种情况下提供提示。
· 屏幕阅读器可以使用Ajax,但是也可能不能正确的读取动态产生的内容。
· 同源策略阻止了一些Ajax技术跨域使用,尽管W3C有关于XMLHttpRequest对象的草案允许这个功能。通过使用一个特别的跨域通道例如页面中的iframe或者使用JSONP可以跨过这种安全限制。
· 异步的回调编程可能导致负责的代码难以维护,调试和测试。
· 因为Ajax的异步特性,客户端发送接收到每块数据都发生在专门为改事件建立的连接上。这就为每个行为增加一种需要,那就是客户端必须轮询服务端,而不是监听,这就会导致额外开销。这种开销会导致Ajax应用有更高的延迟相比于利用websocket技术获取数据。
· 在非HTML5浏览器中,使用Ajax请求创建的动态页面不能自动的注册到浏览器的历史记录中,所以在点击浏览器"回退"按钮时,浏览器不会回到Ajax发生之前的状态,但是会回退到上次访问的页面。这种在页面之间导航而不是在页面状态之间导航的行为可能不是想要的,但是如果需要追踪页面状态,那么对于非HTML5的浏览器一个变通的方案就是使用非透明的iframe触发浏览器历史记录的改变。另一个变通方法就是利用Ajax技术更改URL的片段标识符(URL中在"#"之后的部分)。HTML5提供了一个扩展的API标准来操作浏览器历史记录。
· 动态web页面更新导致很难记标签,返回应用的特性状态。这种问题的解决办法也是存在的,也是利用URL的片段标识符。HTML5提供了解决上面问题的方法。
· 由于Ajax应用的特性,动态页面更新可能会打断用户交互,特别是当网络连接很慢或者不可能的时候。例如,编辑一个搜索框可能会触发一个服务端查询,但是用户可能不知道查询结束时会弹出一个框,如果此时网络很慢,弹窗可能会在一个不恰当的时候弹出,当用户已经开始处理其他的事情时。
· 除了Google,大多数网络爬虫不能执行js代码,所以为了被搜索引擎收录,Web应用必须为那些通过Ajax获取内容的页面提供一个备选页面。

虽然AJAX存在很多弊端,但是随着技术的发展,很多弊端都能够很好地来避免。

参考:

AJAX入门

JavaScript学习总结

AJAX技术详解

原文地址:https://www.cnblogs.com/Chen-XiaoJun/p/6215593.html