Ajax与XMLHttpRequest

Ajax和XMLHttpRequest

Ajax:"Asynchronous JavaScript And XML"即异步JavaScript和XML,是一种创建交互式网页应用的网页开发技术,这项技术的核心是浏览器提供的XMLHttpRequest对象。

XMLHttpRequest的使用

1.设置request header

void setRequestHeader(headerName, headerValue)

  • setRequestHeader必须写在open()方法之后,send()方法之前

2. 获取response header

getAllResponseHeaders()

  • 获取全部可获取(有一些header是获取不到的)的header字段

getResponseHeader(headerName)

  • 获取指定header字段的值(只能获取部分header的值)

3. 指定xhr.response的数据类型

  • 通过设置xhr.response的类型,是告诉浏览器或者xhr如何处理响应数据(对响应数据按照什么样的格式去处理)

xhr.overrideMimeType()

  • 这个方法的作用就是重写response的MIME类型
  • 这个方法必须在send()方法之前进行调用
  • 可以通过这种方式,可以得到纯文本格式的图片内容,获取到数据后再使用相应的编码方法重新构建图片

var xhr = new XMLHtppRequest()
xhr.open('get', 'text.php', true)
xhr.overrideMimeType("text/xml; charset=utf-8")
xhr.send();

根据上面的例子,将response的MIME类型设置为了'text/xml',通过这样的方式,xhr会将响应当做text或者xml来处理,通过xhr.responsexhr.responseText可以获取到文本格式的相应数据,通过xhr.responseXML可以获取到XML格式(是一颗DOM树/DOM对象)的数据


var xhr = new XMLHtppRequest()
xhr.open('get', 'text.php', true)
xhr.overrideMimeType("text/plain; charset=utf-8")
xhr.send();

根据上面的例子,将response的MIME类型设置为了'text/plain',通过这样的方式,xhr会将相应当做text或者plain(纯文本)来处理,通过xhr.responsexhr.responseText可以获取到文本格式的相应数据,通过xhr.responseXML获取到的数据为null,即便数据是XML


xhr.responseType

responseType是XMLHttpRequest leve2中新增的属性,用来指定xhr.response的数据类型

responseType
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
//可以将`xhr.responseType`设置为`"blob"`也可以设置为`" arrayBuffer"`
//xhr.responseType = 'arrayBuffer';
xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status == 200) {
    // this.response就是Blob对象
    var blob = this.response;
    ...
  }
};

xhr.send();

4. 如何获取response数据

xhr提供了3个属性来获取请求返回的数据,分别是:xhr.response, xhr.responseText, xhr.responseXML

  • xhr.response:

    • 无论xhr.responseType的值是什么,只要请求完成,都可以从xhr.response中取到对应的值
    • 请求未完成时,xhr.response的值与xhr.responseType有关,xhr.responseType的值为""(默认值)或者text时,xhr.response的值为"",否则为null
  • xhr.responseText:

    • 只有当responseType设置为''或者text时,才可以使用这个属性获取相应内容
    • 请求未完成、失败时,该值为空字符串
  • xhr.responseXML:

    • 只有当 responseType 为''document时,此时才能调用xhr.responseXML,否则抛错
    • 请求未完成、失败时,该值为null

5. 如何追踪ajax请求的当前状态

  • xhr.readyState属性可以获取ajax的状态,每当xhr.readyState的值发生变化时,就会触发xhr.onreadystatechange事件,可以在这个事件中进行相应的操作
  • 为了保证跨浏览器兼容性,必须在调用open()方法之前指定onreadystatechange事件处理程序
 xhr.onreadystatechange = function () {
    switch(xhr.readyState){
      case 1://OPENED
        //do something
            break;
      case 2://HEADERS_RECEIVED
        //do something
        break;
      case 3://LOADING
        //do something
        break;
      case 4://DONE
        //do something
         break;
    }
xhr.readyState

6 设置请求的超时时间

  • XMLHttpRequest提供了timeout属性来允许设置请求的超时时间。
  • 从请求开始 算起,若超过 timeout 时间请求还没有结束(包括成功/失败),则会触发ontimeout事件,主动结束该请求。
  • 请求开始:xhr.onloadstart事件触发的时候,也就是你调用xhr.send()方法的时候
  • 请求结束:xhr.loadend事件触发的时候。

7 发送同步请求

  • 由open()方法的第三个参数决定,当第三个参数async为true时,发送异步请求,为false时则为同步请求

  • 当xhr为同步请求时,有如下限制:

    • xhr.timeout必须为0
    • xhr.withCredentials必须为 false
    • xhr.responseType必须为""(即默认值)
  • 避免使用同步请求:因为我们无法设置请求超时时间(xhr.timeout为0,即不限时)。在不限制超时的情况下,有可能同步请求一直处于pending状态,服务端迟迟不返回响应,这样整个页面就会一直阻塞,无法响应用户的其他交互。

8 如何获取上传、下载进度

我们可以通过onprogress事件来实时显示进度,默认情况下这个事件每50ms触发一次。需要注意的是,上传过程和下载过程触发的是不同对象的onprogress事件:

  • 上传触发的是xhr.upload对象的 onprogress事件
  • 下载触发的是xhr对象的onprogress事件
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
    if (event.lengthComputable) {
      var completedPercent = event.loaded / event.total;
    }
 }

xhr相关事件

xhr相关事件

每一XMLHttpRequest对象都有一个upload属性,而upload是一个XMLHttpRequestUpload对象.XMLHttpRequest和XMLHttpRequestUpload对象共同拥有上述(除onreadystatechange事件)事件。onreadystatechange是XMLHttpRequest对象独有的事件

事件触发顺序

  1. 触发xhr.onreadystatechange(之后每次readyState变化时,都会触发一次)
  2. 触发xhr.onloadstart

上传阶段开始:

  1. 触发xhr.upload.onloadstart
  2. 触发xhr.upload.onprogress
  3. 触发xhr.upload.onload
  4. 触发xhr.upload.onloadend

上传结束,下载阶段开始:

  1. 触发xhr.onprogress
  2. 触发xhr.onload
  3. 触发xhr.onloadend

发生abort/timeout/error异常的处理

  1. 一旦发生abort或timeout或error异常,先立即中止当前请求
  2. 将 readystate 置为4,并触发 xhr.onreadystatechange事件
  3. 如果上传阶段还没有结束,则依次触发以下事件:
    • xhr.upload.onprogress
    • xhr.upload.[onabort或ontimeout或onerror]
    • xhr.upload.onloadend
    • 注意不会触发onloadstart和onload事件
  4. 触发 xhr.onprogress事件
  5. 触发 xhr.[onabort或ontimeout或onerror]事件
  6. 触发xhr.onloadend 事件
  7. 注意不会触发onloadstart和onload事件
  • 注意: 这时候的xhr.readyState为4,xhr.status为0

在哪个事件中注册成功回调

从上面介绍的事件中,可以知道若xhr请求成功,就会触发xhr.onreadystatechange和xhr.onload两个事件。由于xhr.onreadystatechange是每次xhr.readyState变化时都会触发,而不是xhr.readyState=4时才触发(例如发生abort、timeout、error异常,会先终止当前请求,将readyState设置为4,并触发onreadystatechange事件),因此建议在onload事件中注册成功回调

xhr.onload = function () {
    //如果请求成功
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      //do successCallback
    }
  }
为什么要对xhr.status进行上述判断

xhr.status代表相应的HTTP状态
以2开头的状态码,代表请求已经成功被服务器接收、理解、并接受
状态代码304代表请求的资源并没有修改,可以直接使用浏览器中缓存的版本
其他以3开头的状态代码则表示需要客户端采取进一步的操作才能完成请求。

status和readyState
  • status是响应的HTTP状态,statusText是HTTP状态的说明
  • readyState是表示在请求/响应过程中的当前活动处于哪个阶段

你真的会使用XMLHttpRequest吗?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • Ajax和XMLHttpRequest 我们通常将Ajax等同于XMLHttpRequest,但细究起来它们两个是...
    changxiaonan阅读 2,149评论 0 2
  • 看到标题时,有些同学可能会想:“我已经用xhr成功地发过很多个Ajax请求了,对它的基本操作已经算挺熟练了。” 我...
    前端渣渣阅读 5,705评论 1 12
  • 本文详细介绍了 XMLHttpRequest 相关知识,涉及内容: AJAX、XMLHTTP、XMLHttpReq...
    semlinker阅读 13,516评论 2 18
  • AJAX 原生js操作ajax 1.创建XMLHttpRequest对象 var xhr = new XMLHtt...
    碧玉含香阅读 3,051评论 0 7
  • ajax作为前端开发必需的基础能力之一,你可能会使用它,但并不一定懂得其原理,以及更深入的服务器通信相关的知识。在...
    萧玄辞阅读 764评论 0 0