Ajax工作原理,建立Ajax的过程,使用Ajax的一些注意事项

posted @ Oct 7, 2015

之前总结了前端跨域请求数据的方法,今天闲下来整理一些最常用的,也是带动Javascript发展的Ajax。

基本原理和概念

AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。AJAX 是一种用于创建快速动态网页的技术。AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。 __baidu

  • 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
  • 传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。

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

注意

Ajax是不能跨域的,如需跨域,可以使用document.domain=‘a.com’;或者使用服务器代理,代理XMLHttpRequest文件

建立Ajax的过程

Ajax是基于现有的Internet标准,并且联合使用它们:

XMLHttpRequest 对象 (异步的与服务器交换数据) JavaScript/DOM (信息显示/交互) CSS (给数据定义样式) XML (作为转换数据的格式) 图片描述

Ajax的核心是创建 XMLHttpRequest 对象

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

创建Ajax对象:

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

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

 //创建一个ajax对象 ie6以下
 //new ActiveXObject('Microsoft.XMLHTTP')

 var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');//三元操作
 /*
 var xhr = null;
 if (window.XMLHttpRequest) {
     xhr = new XMLHttpRequest();
 } else {
     xhr = new ActiveXObject('Microsoft.XMLHTTP');
 }*/

 /*try {
     xhr = new XMLHttpRequest();
 } catch (e) {
     xhr = new ActiveXObject('Microsoft.XMLHTTP');
 }
 */
//以上提供了三种方法,任选一种	
//alert( xhr.readyState );完成第一步

连接服务器

oAjax.open(方法,url,是否异步) > 我们都知道,Ajax即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。所以,Ajax天生就是工作在异步模式的(异步为true,同步false)

同步和异步

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

(简单点说:同步就是只能一件一件事的来做,而异步就是可以多件事同时进行)

open方法 参数
1.打开方式
2.地址
3.是否异步 异步:非阻塞 前面的代码不会影响后面代码的执行
同步:阻塞 前面的代码会影响后面代码的执行
tip:那么什么时候要用到同步呢,就是后面的代码需要前面的代码完成后才能开始执行时,就要使用同步策略。

 xhr.open('get', 'test.txt', true);

发送请求send()

send 里面的参数get方法可以不填或者null;post方法填要传到后台的数据参数。

服务器返回内容。处理返回数据

详细信息见下面分析

  • readyState : ajax工作状态 0 1 2 3 4
  • responseText : ajax请求返回的内容就被存放到这个属性下面.但是数据类型是string类型。需要使用eval来转换,然后才能使用。
  • responseXml : 返回XML格式的数据
  • on readystate change : 当readyState状态改变的时候触发这个事件
  • status : 服务器状态,http状态码
  • statusText : 状态说明

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
        if (xhr.status == 200) {
            // 处理数据
            // alert(xhr.responseText);
            oB.innerHTML = xhr.responseText;
            /*var str = xhr.responseText;
            oB.innerHTMl = eval(str);*/
        } else {
            alert('出错了,Erro' + xhr.status);
        }
    }

} 一个示例

function getDoc(){
    var xmlhttp;
    if(window.xmlhttpRequest){
        xmlhttp=new XMLHttpRequest();
    }
    else{
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");//for IE6
    }
    xmlhttp.onreadystatechange = function(){
        if(xmlhttp.readyState==4&&xmlhttp.status==200){
            document.getElementById("myId").innerHTML=xmlhttp.responseText;
        }
    }
    xmlhttp.open("GET", index.php,true);
    xmlhttp.send();
}

<body>
    <button type="button" onclick="getDoc()">请求数据</button>
</body>

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);

XHR对象

XMLHttpRequest这个对象的属性:

1、 属性

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

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

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

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

2、 状态

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

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

http状态码

1字头:消息。这一类型的状态码,代表请求已被接受,需要继续处理。 2字头:成功。这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。 3字头:重定向。这类状态码代表需要客户端采取进一步的操作才能完成请求。 4字头:客户端错误。这类状态码代表了客户端看起来可能发生错误,妨碍了服务器的处理。 5字头:服务器错误。这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生

另附:http状态码详解

w3cschool HTTP 状态消息

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) : 使用指定的名称和值设置请求头

<script type="text/javascript">
        var oAjax =oAjax();
        alert(oAjax.readyState);//弹出"0"
        oAjax.open("get","index.html",true);
        alert(oAjax.readyState);//弹出"1"
        oAjax.send(null);
        alert(oAjax.readyState);//IE下弹出4,而firefox是2
        //可以通过readystatechange事件监听
        oAjax = XHR();
        oAjax.onreadystatechange = function () {
            alert(oAjax.readyState);//Firefox下依次是1,2,3,4但最后还会再来个1
            //IE下则是1,1,3,4
        };
        oAjax.open("get","index.txt",true);
        oAjax.send(null);
</script>

jQuery中的Ajax

$.load()方法

.load()方法是局部方法,因为他需要一个包含元素的jQuery对象作为前缀,而$.get()和$.post()是全局方法,无需指定某个元素,对于用途而言,.load()适合做静态文件的异步获取,而对于需要传递参数到服务器页面的,$.get()和$.post()更加合适。

$(function () {
    $("input").click(function () {
        $.get('test.php?url=baidu.com', function (response,status,xhr) {
            $('#box').html(response);
        })
    })
});

$.post()

POST提交不能使用url传参。post提交可以使用字符串形式的键值对形式传参,自动转换为http消息实体传参

$(function () {
    $("input").click(function () {
        $.post('test.php','url=baidu.com', function (response,status,xhr) {
            $('#box').html(response);
        })
    })
}); //post提交可以使用对象键值对

$(function () {
    $("input").click(function () {
        $.post('test.php',{
                url:'baidu.com'//post提交可以使用对象键值对
            }, function (response,status,xhr) {
            $('#box').html(response);
        })
    })
});

$.get()方法

$.get()方法有四个参数,前面三个参数和.load()一样,多了一个第四参数type,即服务器返回的内容格式,包括xml,json,script,html,text等,第一个参数为必选参数,后面三个为可选参数

$.ajax()方法

$.ajax()是所有Ajax方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装,这个方法只有一个参数,传递一个 各个功能键值对的对象。

$.ajax()方法对象参数列表

参数 类型 说明
url string 发送请求的地址
type string 请求方法,默认GET
timeout Number 设置请求超时的时间
data Object或String 发送到服务器的对象,键值对字符串或对象
datatype String 返回的数据类型,比如html,XML,json等
success Function 请求成功后调用的回调函数
complete Function 请求完成后调用的回调函数
error Function 请求失败后调用的回调函数

$(function () {
    $("input").click(function () {
        $.ajax({
            type : "POST",
            url: 'test.php',
            data:{
                url: 'baidu.com'
            },
            success : function(response,status,xhr){
                $('#box').html(response);
            }
        })
    })
});

表单序列化

Ajax用的最多的地方莫过于表单操作,而传统的表单操作是通过submit提交将数据传输到服务器,如果使用Ajax异步处理 的话,我们需要将每个表单元素获取才能提交,这样工作效率就大大降低

<body>
<form action="">
    用户名: <input type="text" name="user" />
    邮件: <input type="text" name="email" />
    <input type="button" value="提交"/>
</form>
<div id="box"></div>
<script type="text/javascript">
    $(function () {
        $("form input[type=button]").click(function () {
            $.ajax({
                type: 'POST',
                url: 'test.php',
                data: {
                    user: $('form input[name=user]').val(),
                    email: $("form input[name=email]").val(),
                },
                success: function(response){
                    $("#box").html(response);
                }
            })
        })
    });
</script>
</body>

表单元素特别多的情况下应采用表单序列化,即data:$(“form”).serialize();//得到的是字符串键值对,并且对url进行编码

serialize()方法不但可以序列化表单内的元素,还可以直接获取单选框,复选框和下拉列表框等内容

<body>
<form action="">
    用户名: <input type="text" name="user" />
    邮件: <input type="text" name="email" />
    <input type="button" value="提交"/>
    <input type="radio" name="sex" value="男"/>男
    <input type="radio" name="sex" value="女"/>女
    <input type="button" value="submit"/>
</form>
<div id="box"></div>
<script>
    $(function () {
        $("form input[name=sex]").click(function () {
            $('#box').html(decodeURIComponent($(this).serialize()));
        })
    })
</script>
</body>

传统Ajax问题

传统的ajax有如下的问题:

1、可以无刷新改变页面内容,但无法改变页面URL

2、为了更好的可访问性,内容发生改变后,通常改变URL的hash

3、hash的方式不能很好的处理浏览器的前进、后退等问题

4、进而浏览器引入了onhashchange的接口,不支持的浏览器只能定时去判断hash是否改变

5、但这种方式对搜索引擎很不友好

6、twitter和google约定了使用#!xxx(即hash第一个字符为!),搜索引擎进行支持。