文档章节

JavaScript-Ajax

Leezy__
 Leezy__
发布于 2016/08/05 14:56
字数 3288
阅读 22
收藏 0

Ajax通信与数据格式无关,从服务器获取的数据不一定是XML数据。

Ajax的核心:XMLHttpRequest对象(简称XHR)

在XHR对象之前,Ajax通信通常使用hack手段,如使用隐藏的或内嵌的框架。

XHR对象为向服务器发送信息和解析服务器响应提供了流畅的接口。

 

1.XMLHttpRequest对象

IE5是第一款引进XHR对象的浏览器,通过MSXML库中的ActiveX对象实现(有3个版本)。

兼容所有浏览器,创建XHR对象:

function createXHR(){
    if (typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject != "undefined"){
        if (typeof arguments.callee.activeXString != "string"){
            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                            "MSXML2.XMLHttp"],
                i, len;

            for (i=0,len=versions.length; i < len; i++){
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex){
                    //skip
                }
            }
        }

        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("No XHR object available.");
    }
}

之后就能在所有浏览器创建XHR对象:var xhr = createrXHR();

 

2.原生XHR对象 (支持的浏览器: IE7+、FF、Chrome、Opera、Safari)

通过XMLHttpRequest构建函数,创建XHR对象:

xhr =  XMLHttpRequest();

 

3.XHR用法

3.1.open()

open() 3个参数: 发送的类型、请求的URL、表是否异步的布尔值

xhr.open("get","/index", false);

    ①URl为相对于执行代码的当前页,或绝对地址;

    ②false为同步,JavaScript代码会在服务器响应后再继续执行;

    ③调用open()只是启动一个请求以备发送,还没真正发送;

    ④只能在同个域中使用相同端口和协议的URL发送请求。

 

3.2.send()

send() 1个参数: 请求主体发送的数据,不需要通过请求主体发送数据则传入null。

调用send()后,请求被分派到服务器。

xhr.open("get","example.php", false) ;

xhr.send();

 

3.3.收到响应后,响应数据会自动填充XHR对象的属性:

responseText:作为响应的主体被返回的文本;

responseXML:若响应的内容类型”text/xml”或”application/xml”,此属性保存响应数据XML DOM文档;

status:响应的HTTP状态;

statusText:HTTP状态的说明;

 

☆:无论什么内容类型,响应主体的内容都会保存在responseText属性中。对于非XML数据,responseXML属性值为null。

 

3.4.status属性确认响应是否成功返回

HTTP状态代:

    200:响应有效,responseText属性已就绪,内容类型正确下的responseXML也可访问。

    304:响应有效,只是请求的资源并为修改,可直接使用浏览器中缓存的版本。

正确检查上述2种状态代码:

if ((xhr.status >= 200 && xhr.status <=300) || xhr.status == 304) {
     alert(xhr.responseText);
} else {
     alert("Request was unsuccessful:" + xhr.status);
};

 

3.5.readystate属性

该属性存储请求/响应过程的当前活动状态。

    0 : 未初始化,未调用open();

    1 : 启动,调用了open();

    2 : 发送,调用了send(),未接受响应;

    3 : 接受,已接受部分响应;

    4 : 完成,已接受全部响应,且可在客户端使用。

 

3.6.readystatechange事件

该事件,在readystate属性值改变时触发。

var xhr = createXHR();
xhr.onreadystatechange = function(event){
    if (xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};

xhr.open("get", "example.txt", true);

①必须在调用open()之前知道readystatechange事件的事件处理程序,确保兼容。

②该事件处理程序中没有传递event对象,必须通过XHR对象本地来确定下一步怎么做;

③使用xhr对象而不使用this对象,是因为onreadystatechange事件处理程序的作用域问题。使用this对象在一些浏览器会导致函数执行失败或发生错误。

 

3.7.abort()

调用此方法可取消异步请求:xhr.abort();

调用后,xhr对象停止触发事件,不允许访问如何与响应相关的属性;

终止请求后,应对XHR对象进行解引用操作,不建议重用XHR对象。

 

4.HTTP头部信息

发送请求时的头部信息:

    Accept:浏览器能够处理的内容类型

    Accept-Charset:浏览器能够显示的字符集

    Accept-Encoding:浏览器能够处理的压缩编码

    Accept-Language:浏览器当前设置的语言

    Connection:浏览器与服务器之间连接的类型

    Cookie:当前页面设置的如何Cookie

    Host:发送请求耳洞页面所在域

    Referer:发出请求的页面的URI

    User-Agent:浏览器的用户代理字符串

 

setRequestHeader() : 设置自定义头部信息。2个参数:头部字段名称、头部信息值。

需在open()方法之后调用send()之前调用setRequestHeader(),才能成功发送请求头部信息。

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

getRequestHeader() : 获取指定的相应头部信息

xhr.getRequestHeader(“MyHeader”);

getAllRequestHeader() : 获取一个包含所有头部信息的长字符串

xhr.getAllRequestHeader();

 

5.GET请求

对于XHR对象,位于open()的URL末尾的查询字符串 需经过编码,使用encodeURIComponent()编码。

名-值对需用和号(&)分隔。

自定义函数,添加URL查询字符串参数:

function submitData(){
    var xhr = createXHR();        
    xhr.onreadystatechange = function(event){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                alert(xhr.responseText);
            } else {
                alert("Request was unsuccessful: " + xhr.status);

            }

        }

    };

 

6.POST请求

由于XHR其初的设计是为了处理XML,故在send()中可传入XHR DOM文档。

 

6.1.服务端读取POST数据

①默认情况下,服务器对POST请求和提交Web表单不会一视同仁,故服务端需要程序来读取发送的原始数据,并解析出有用部分。

②XHR模拟表单提交:

    1.将Content-Type头部信息设置为application/x-www-form-urlencoded (即表单提交时的内容问题);

    2.以适当格式创建一个字符串。(通过serialize()函数创建该字符串,序列化表单数据)

function submitData(){
    var xhr = createXHR();
    xhr.onreadystatechange = function(event){
        if (xhr.readyState == 4){
            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
                alert(xhr.responseText);
            } else {
                alert("Request was unsuccessful: " + xhr.status);
            }
        }
    };
    xhr.open("post", "postexample.php", true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    var form = document.getElementById("user-info");
    xhr.send(serialize(form));
}

 

7.CORS 跨源资源共享

跨域安全策略限制了Ajax的异步通信,CORS则是定义了跨域时,客户端和服务器的沟通。

CORS思想:使用自定义HTTP头部让浏览器与服务器进行沟通,从而决定请求/响应的成功与否。

 

7.1.给一个请求附加Origin头部,包含请求页面的源信息(协议、域名 和 端口)

Origin: http://www.domain.com

服务器根据Origin判断是否接收请求,接收则在Access-Control-Allow-Origin头部会发相同信息。

Access-Control-Allow-Origin: http://www.domain.com

若无此头部或头部信息不匹配,浏览器将驳回请求。

☆请求和响应不会包含cookie信息。

 

7.2.IE8+对CORS的实现

IE8引入的XDR(XDomainRequest)类型,类型XHR,可实现安全可靠的跨域通信。

 

7.2.1.XDR与XHR的不同之处:

①cookie不会随请求发送,也不会随响应返回;

②只能设置请求头部信息中的Content-Type字段;

③不能访问响应头部信息;

④只支持GET和POST请求

被请求的资源可判断用户代理、来源页面等如何数据 来决定是否设置Access-Control-Allow-Origin头部

 

7.2.2.XDR使用方法类似XHR,创建一个XDomainRequest实例,调用open(),再调用send()

XDR只能执行异步请求,所以open()方法只有两个参数,请求的类型和URL。

在收到响应后,只能访问响应的原始文本,无法确定响应的状态代码。

只要响应有效就会触发load事件,响应的数据会保存在responseText属性中。

如果失败(如,响应中缺少Access-Control-Allow-Origin头部)就会触发error事件,但该事件无有用信息,需要自定义一个onerror事件句柄。

var xdr = new XDomainRequest();
xdr.onload = function(){
    alert(xdr.responseText);
};
xdr.onerror = function(){
    alert("Error!");
};

xdr.open("get", "http://www.somewhere-else.com/xdr.php");
xdr.send(null);

在请求返回前调用abort()可终止请求。

 

7.2.3.XDR也支持timeout属性及ontiomout事件处理程序,在运行超过timeout设定的秒数后,调用ontimeout事件句柄

为支持POST请求,XDR提供了contentType属性,用于表示发送数据的格式。

contentType属性是XDR对象影响头部信息的唯一方式。

xdr.contentType = "application/x-www-form-urlencoded";

 

7.3.其他浏览器对CORS的实现

FF等浏览器都通过XMLHttpRequest对象实现了对CORS的原生支持。要请求另一个域中的资源时,使用标准XHR对象并在open()中传入绝对URL即可。

var xhr = createXHR();
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    }
};
xhr.open("get", "http://www.abc.com/page/", true);
xhr.send(null);

与IE不同,通过跨域XHR对象可以访问status属性和statusText属性,也可同步请求。

 

7.3.1.跨域XHR的限制:

①不能使用setRequestHeader()设置自定义头部;

②不能发送和接收cookie;

③调用getAllResponseHeader()方法总会返回空字符串。

 

7.3.2.无论同源请求还是跨域请求都是使用相同的接口,故对于本地资源,最好用相对URL,对远程资源再用绝对URL。

这样能消除歧义,避免出现限制访问头部或本地cookie信息等问题。

 

7.4.跨浏览器的CORS(IE8+、FF等)

检测XHR是否支持CORS的方法:检查是否存在withCredentials属性,在结合检测XDomainRequest对象是否存在。

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

var request = createCORSRequest("get", "http://www.somewhere-else.com/xdr.php");
if (request){
    request.onload = function(){
        //do something with request.responseText
    };
    request.send();
}

上述createCORSRequest()函数返回的对象的属性(XHR和XDR的共同属性):

①abort():停止正在进行的请求;

②onerror:用于替代onreadystatechange检测错误;

③onload:用于代替onreadystatechange检测成功;

④responseText:用于取得响应内容;

⑤send():用于发送请求。

 

8.其他跨域技术

在CORS出现前,常利用DOM中能够执行跨域请求的功能,在不依赖XHR对象时,也能发送某种请求。

与COSR不同的是,不用修改服务器代码。

 

8.1.图像Ping

使用<img>标签,由于可以从任何网页加载图像,故常是在线广告跟踪浏览量的主要方式。

可动态创建图像,使用它们的onload和onerror事件句柄,确定是否接受到了响应。

var img = new Image();
img.onload = img.onerror = function(){
    alert("Done!");
};

img.src = "http://www.example.com/test?name=Nicholas";

图像Ping是与服务器进行简单、单向的跨域通信的一种方式。请求的数据通过查询字符串形式发送,响应可以是任何内容,通常是像素图或204响应。虽然通过图像Ping,浏览器得不到任何具体数据,但通过侦听load和error事件,能找到响应收到的时间。

图像Ping常用于跟踪用户点击页面 或动态广告曝光次数。

缺点:①只能发送GET请求;②无法访问服务器响应文本。

 

8.2.JSONP

JSONP(JSON width Padding)填充式JSON或参数式JSON,类似JSON,是包含在函数调用中的JSON:

callback( {"name" : "value"} );

 

8.2.1.JSONP有两个部分:回调函数和数据

回调函数:当响应到来时应该在页面中调用的函数。回调函数的名称在请求中指定。

数据:传入回调函数的JSON数据。

 

8.2.2.JSONP通过动态<script>元素,为其src属性指定一个跨域的URL。类似<img>元素,即都能不受限制地跨域加载资源。

JSONP为有效的JavaScript代码,在请求完成即JSONP响应 加载到页面后就会立即执行。

function handleResponse(response){
    alert("You're at IP address " + response.ip + ", which is in " + response.city + ", " + response.region_name);
}

var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);

headleResponse()为回调函数,将在响应到来后执行。

 

8.2.3.JSONP之所以流行,是因为

①能够直接访问响应文本;

②支持浏览器与服务器之间的双向通信。

①JSONP从其他域加载代码执行,因此该域必须安全可靠;

②很难确保JSONP请求是否失败。

 

8.3.Comet ”服务器推送" 

Ajax从页面想服务器请求数据,Comet则是服务器向页面推送数据,Comet能近乎实时地向页面推送信息。

 

8.3.1.实现Comet的2种方式:长轮询和流

①长轮询:与短轮询相反,页面发送一个请求,服务器一直保持连接打开,直到有数据可发送时就向页面发送数据。接收完数据后浏览器关闭连接,随机又发送一个新请求,在页面打开期间如此循环。【短轮询是服务器立即发送数据,即使数据无效,长轮询是等待发送响应。】轮询的优点是,所有浏览器都支持。通过XHR对象和setTimeout()实现。

②HTTP流:它在网页的整个生命周期内只使用一个HTTP连接。浏览器发送一个请求,服务器保持连接打开,再周期性向浏览器发送数据.

实现HTTP流的关键:所有服务器端语言都支持打印到输出缓存然后刷新的功能。(将输出缓存中的内容一次性全部发送给客户端)

var xhr = new XMLHttpRequest(),
    received = 0;
xhr.open("get", url, true);
xhr.onreadystatechange = function(){
    var result;
    if (xhr.readyState == 3){
        //get only the new data and adjust counter
        result = xhr.responseText.substring(received);
        received += result.length;
        //call the progress callback
        progress(result);
    } else if (xhr.readyState == 4){
        finished(xhr.responseText);
    }
};
xhr.send(null);
return xhr;
}
var client = createStreamingClient("streaming.php", function(data){
    alert("Received: " + data);
}, function(data){
    alert("Done!");
});

 

© 著作权归作者所有

上一篇: JavaScript-cookie
下一篇: ES6学习-解构赋值
Leezy__
粉丝 1
博文 11
码字总数 11304
作品 0
朝阳
程序员
私信 提问
JavaScript开发过程中遇到的各种个问题、bug、坑

要区分js对象与json字符串 json实际就是js对象的文本表示形式(字符串) ajax提交数据时,data中需要写的是js对象,而不是json。 使用JSON.stringify()得到的就是json(字符串),而不是js对...

城市之雾
2018/07/05
0
0
有个事情不明白,请大神指教,比如我有一个html、js、php文件,但是我想把ajax写到js文件当中,然后再html引入这个js文件,怎么不行啊

有个事情不明白,请大神指教,比如我有一个html、js、php文件,但是我想把ajax写到js文件当中,然后再html引入这个js文件,但是html里面的数据字段我直接放到js的ajax里面,然后在ajax里面通...

打飞机的猪猪侠
2017/01/05
361
4
jQuery学习笔记180924

jQuery - AJAX 简介 什么是 AJAX? AJAX = 异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。 简短地说,在不重载整个网页的情况下,AJAX 通过后台加载数据,并在网页上进行显示...

颖伙虫
2018/09/24
0
0
[Android]PhoneGap源码分析——CallbackServer异步回调

PhoneGap的js回调有几种实现方式。其中一种是ajax。 我们先来看一下js端相关代码: // file: lib/android/plugin/android/callback.jsdefine("cordova/plugin/android/callback", function(......

亭子happy
2012/09/24
0
1
《她理财》招聘web前端开发工程师

1.专科及以上学历 2.至少1年以上Web前端开发经验, 精通XHTML,HTML,Ajax,JavaScript,CSS等技术,熟悉页面架构和DIV CSS布局,理解Web标准,在 JavaScript、CSS、AJAX等方面有深入的研究和...

若孤
2012/04/23
578
4

没有更多内容

加载失败,请刷新页面

加载更多

利用mybatis generator生成实体类、Mapper接口以及对应的XML文件

项目中通常会遇到数据的持久化,如果是采用mybatis的orm,就会涉及到生成xml的问题,刚好mybatis官网提供了这么个插件MyBatis Generator,效果简直是棒呆。 1. 首先需要在build.gradle文件中...

啊哈关关
今天
2
0
SpringSocial相关的知识点

使用SprigSocial开发第三方登录 核心类 ServiceProvider(AbstractOauth2ServiceProvider):主要负责实现server提供商(例如QQ,微信等共有的东西),默认实现类是AbstractOauth2ServiceProvider...

chendom
今天
1
0
Java并发之AQS详解

一、概述   谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!   类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源...

群星纪元
昨天
2
0
Fabric-sdk-java最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程。 如果希望快速掌握F...

汇智网教程
昨天
2
0
react 子组件监听props 变化

componentWillReceiveProps //已经被废弃 getDerivedStateFromProps// 推荐使用//如果条件不存在必须要返回null static getDerivedStateFromProps(props, current_stat...

一箭落旄头
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部