XMLHttpRequest 基础

官方文档
超好用的API接口平台分享,含免费API
JSON API免费接口
XMLHttpRequest 对象用于在后台与服务器交换数据。
XMLHttpRequest 对象是开发者的梦想,因为您能够:

  • 在不重新加载页面的情况下更新网页
  • 在页面已加载后从服务器请求数据
  • 在页面已加载后从服务器接收数据
  • 在后台向服务器发送数据

1. 创建 XMLHttpRequest 对象

var xhr = new xmlHttpRequest();

老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

IE 5.0 版本开始以 ActiveX 组件形式支持 XMLHttpRequest,IE 7.0 版本开始标准化 XMLHttpRequest。不过所有浏览器实现的 XMLHttpRequest 对象都提供相同的接口和用法。
可以把定义 XMLHttpRequest 对象进行封装
下面示例使用工厂模式把定义 XMLHttpRequest 对象进行封装,这样只需要调用 creatXHR() 方法就可以返回一个 XMLHttpRequest 对象。

function createXHR(){
  var  XHR = [//兼容不同浏览器和版本得创建函数数组
    function() {return new XMLHttpRequest ()},
    function(){ return new ActiveXObject("Msxml2.XMLHTTP")},
    function(){ return new ActiveXObject("Msxml3.XMLHTTPP")},
    function(){ return new ActiveXObject("Microsoft.XMLHTTP")}
  ];
  var xhr = null;  
  for(let index = 0;index < XHR.length;index++){
    try{
      xhr = XHR[index]()
    }catch(err){
      console.error(err)
      continue
    }
    break;
  }
  return xhr
}

在上面代码中,首先定义一个数组,收集各种创建 XMLHttpRequest 对象的函数。第 1 个函数是标准用法,其他函数主要针对 IE 浏览器的不同版本尝试创建 ActiveX 对象。然后设置变量 xhr 为 null,表示为空对象。接着遍历工厂内所有函数并尝试执行它们,为了避免发生异常,把所有调用函数放在 try 中执行,如果发生错误,则在 catch 中捕获异常并执行 continue 命令,返回继续执行,避免抛出异常。如果创建成功,则中止循环,返回 XMLHttpRequest 对象。

2. 建立连接

在 JavaScript 中,使用 XMLHttpRequest 对象的 open() 方法可以建立一个 HTTP 请求。用法如下:

xhr.open(method,url,async,username,password)

xhr.open(method, url, async, username, password);

其中 xhr 表示 XMLHttpRequest 对象,open() 方法包含 5 个参数,说明如下:

  • method :要使用的 HTTP 方法,比如 GET、POST、PUT、DELETE、等,大小写不敏感。对于非 HTTP(S) URL 被忽略。

  • url: 一个 DOMString 表示要向其发送请求的 URL。

  • async:一个可选的布尔参数,表示是否异步执行操作,默认为 true。如果值为 false,send() 方法直到收到答复前不会返回,当状态改变时会立即调用 onreadystatechange 属性指定的回调函数。如果 true,已完成事务的通知可供事件监听器使用。如果 multipart 属性为 true 则这个必须为 true,否则将引发异常。
    备注:主线程上的同步请求很容易破坏用户体验,应该避免;实际上,许多浏览器已完全弃用主线程上的同步 XHR 支持。在 Worker 中允许同步请求

  • username:可选参数,如果服务器需要验证,该参数指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。

  • password:可选参数,验证信息中的密码部分,如果用户名为空,则该值将被忽略。

3. 建立连接后,可以使用 send() 方法发送请求。用法如下:

xhr.send(body);//选填

XMLHttpRequest.send() 方法用于发送 HTTP 请求。如果是异步请求(默认为异步请求),则此方法会在请求发送后立即返回;如果是同步请求,则此方法直到响应到达后才会返回。XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
如果没有使用 setRequestHeader() 方法设置 Accept 头部信息,则会发送带有 "* / *"Accept 头部。
如果 body 没有指定值,则默认值为 null。
发送请求后,可以使用 XMLHttpRequest 对象的 responseBody、responseStream、responseText 或 responseXML 属等待接收响应数据
在 XHR 请求中要发送的数据体。可以是:

  • 可以为 Document, 在这种情况下,它在发送之前被序列化。
    以下是一些可能的解决方案:
    解决方案1:使用XMLSerializer
var serializer = new XMLSerializer();
var xml = serializer.serializeToString(document);
var xhr = new XMLHttpRequest();
xhr.open("POST", "some/url", true);
xhr.send(xml);

解决方案2:使用document.documentElement.outerHTML

var xhr = new XMLHttpRequest();
xhr.open("POST", "some/url", true);
xhr.send(document.documentElement.outerHTML);

解决方案3:使用document.documentElement.innerHTML

var xhr = new XMLHttpRequest();
xhr.open("POST", "some/url", true);
xhr.send(document.documentElement.innerHTML);

如果发送的数据是 Document 对象,需要在发送之前将其序列化。当发送一个 Document 对象时,Firefox 3 之前的版本都是使用 UTF-8 编码发送请求的;FireFox 3 则使用由 body.xmlEncoding 指定的编码格式正确的发送文档,但如果未指定编码格式,则使用 UTF-8 编码格式发送。

如果是一个 nsIInputStream 接口,它必须与 nsIUploadChannel 的 setUploadStream() 方法兼容。在这种情况下,将 Content-Length 的头部添加到请求中,它的值则使用 nsIInputStream 接口的 available() 方法获取。任何报头包括在数据流顶部的都会被当做报文主体。所以,应该在发送请求即调用 send() 方法之前使用setRequestHeader() 方法设置 Content-Type 头部来指定数据流的 MIME 类型。

发送二进制内容的最佳方法(如上传文件)是使用一个与 send() 方法结合的 ArrayBufferView 或者 Blobs

XMLHttpRequest

  1. 实例方法
  • abort
    可冒泡:No;可取消:No;事件处理程序属性:onabort
    当一个请求终止时 abort 事件被触发,比如程序执行 XMLHttpRequest.abort()
let xhr = new XMLHttpRequest();
let url = 'https://api.uomg.com/api/rand.qinghua';
xhr.onabort = function (params) {
    console.log('请求被abort()取消了');
})
xhr.open('POST', url, true);
xhr.send('format=json');
setTimeout(() => {
    xhr.abort()
}, 10)
  • error
    可冒泡:No;可取消:No;事件处理程序属性:onerror
    当请求遇到错误时,将触发error 事件。
let xhr = new XMLHttpRequest();
let url = 'https://somewhere.org/i-dont-exist';
xhr.onerror = function (params) {
    console.log('请求遇到错误了');
}
xhr.open('GET', url);
xhr.send()
  • load
    可冒泡:No;可取消:No;事件处理程序属性:onload
    当一个XMLHttpRequest请求完成的时候会触发load 事件。
let xhr = new XMLHttpRequest();
let url = 'https://api.uomg.com/api/rand.qinghua';
xhr.onload= function (params) {
    console.log('请求完成了');
}
xhr.open('GET', url);
xhr.send()
  • loadstart
    当程序开始加载时,loadstart 事件将被触发。这个事件可以被 XMLHttpRequest 调用,也适用于 <img><video> 元素。
let xhr = new XMLHttpRequest();
let url = 'https://api.uomg.com/api/rand.qinghua';
xhr.onloadstart = function (params) {
    console.log('request loadstart');
}
xhr.onload= function (params) {
    console.log('request onload');
}
xhr.open('GET', url);
xhr.send()
  • loadend
    loadend 事件总是在一个资源的加载进度停止之后被触发 (例如,在已经触发“error”,“abort”或“load”事件之后)。这适用于 XMLHttpRequest 调用,以及 <img><video> 之类元素的内容。
let xhr = new XMLHttpRequest();
let url = 'https://api.uomg.com/api/rand.qinghua';
xhr.onloadend = function (params) {
    console.log('request loadend ');//再执行loadend 
}
xhr.onload= function (params) {
    console.log('request onload');//先执行onload
}
xhr.open('GET', url);
xhr.send()
  • progress
    可冒泡:No;可取消:No;事件处理程序属性:onprogress
    progress 事件会在请求接收到数据的时候被周期性触发。
    XMLHttpRequest对象在进行文件上传或下载时,可以利用其progress事件来跟踪文件的上传或下载进度。
var xhr = new XMLHttpRequest();
var file = document.querySelector('input[type="file"]').files[0];
 
var formData = new FormData();
formData.append('file', file);
 
xhr.open('POST', '/upload', true);
 
xhr.upload.onprogress = function(e) {
  if (e.lengthComputable) {
    var percentComplete = (e.loaded / e.total) * 100;
    console.log(percentComplete.toFixed(2) + '%');
  }
};
 
xhr.send(formData);
  • onreadystatechange
    只要 readyState 属性发生变化,就会调用相应的处理函数。这个回调函数会被用户线程所调用。XMLHttpRequest.onreadystatechange 会在 XMLHttpRequestreadyState 属性发生改变时触发 readystatechange 事件的时候被调用。
    警告:这个方法不该用于同步的 requests 对象,并且不能在内部 (C++) 代码中使用。
    当一个 XMLHttpRequest 请求abort方法取消时,其对应的 readystatechange 事件不会被触发。
var xhr = new XMLHttpRequest(),
  method = "GET",
  url = "https://developer.mozilla.org/";

xhr.open(method, url, true);
xhr.onreadystatechange = function () {
  if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};
xhr.send();
  • timeout
    可冒泡:No;可取消:No;事件处理程序属性:ontimeout
    当进度由于预定时间到期而终止时,会触发 timeout 事件。
let xhr = new XMLHttpRequest();
let url = 'https://api.uomg.com/api/rand.qinghua';
xhr.ontimeout= function (params) {
    console.error("Timeout!!");
}
xhr.open('GET', url);
xhr.send()
  1. 实例属性
  • status
    只读属性 XMLHttpRequest.status 返回了 XMLHttpRequest 响应中的数字状态码。status 的值是一个无符号短整型。在请求完成前,status 的值为 0。值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为 0。status 码是标准的 HTTP status codes。举个例子,status 200 代表一个成功的请求。如果服务器响应中没有明确指定 status 码,XMLHttpRequest.status 将会默认为 200
    HTTP 响应状态码用来表明特定HTTP请求是否成功完成。 响应被归为以下五大类:
  1. 信息响应 (100199)
  2. 成功响应 (200299)
  3. 重定向消息 (300399)
  4. 客户端错误响应 (400499)
  5. 服务端错误响应 (500599)
  • statusText
    只读属性 XMLHttpRequest.statusText 返回了XMLHttpRequest 请求中由服务器返回的一个DOMString类型的文本信息,这则信息中也包含了响应的数字状态码。不同于使用一个数字来指示的状态码XMLHTTPRequest.status,这个属性包含了返回状态对应的文本信息,例如"OK"或是"Not Found"。如果请求的状态readyState的值为"UNSENT"或者"OPENED",则这个属性的值将会是一个空字符串。如果服务器未明确指定一个状态文本信息,则statusText的值将会被自动赋值为"OK"。
  • readyState
    XMLHttpRequest.readyState 属性返回一个 XMLHttpRequest 代理当前所处的状态。一个 XHR 代理总是处于下列状态中的一个:
    状态 描述
    0 UNSENT 代理被创建,但尚未调用 open() 方法。
    1 OPENED open() 方法已经被调用。
    2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
    3 LOADING 下载中;responseText 属性已经包含部分数据。
    4 DONE 下载操作已完成。
  • responseType
    responseType 是一个枚举字符串值,用于指定响应中包含的数据类型。
    它还允许作者更改响应类型。如果将 responseType 的值设置为空字符串,则会使用 text 作为默认值。

    Global_Objects/String类型的值,指定响应包含的数据类型。它可以采用以下值:
    描述
    '' 空的 responseType 字符串与默认类型 "text" 相同。
    arraybuffer response 是一个包含二进制数据的 JavaScript ArrayBuffer
    blob response是一个包含二进制数据的 Blob对象。
    document response是一个HTML Document或XML XMLDocument,根据接收到的数据的 MIME 类型而定。请参阅`XMLHttpRequest 中的 HTML,了解有关使用 XHR 获取 HTML 内容的更多信息。
    json response是通过将接收到的数据内容解析为JSON而创建的 JavaScript 对象。
    text response是DOMString 对象中的文本。
    ms-stream response是是流式下载的一部分;此响应类型仅允许用于下载请求,并且仅受 Internet Explorer 支持
  • response
    XMLHttpRequest的 response 属性返回响应的正文。返回的类型为 ArrayBufferBlobDocumentJavaScript Object或字符串中的一个。这取决于请求的responseType属性。

    一个对象,其类型取决于responseType 的值。你可以尝试设置 responseType 的值,以便请求特定的类型的数据。 responseType 要在调用open()初始化请求之后以及在调用send()发送请求到服务器之前设置。
    如果请求尚未完成或未成功,则取值是 null。例外的,读取文本数据时如果将 responseType 的值设置成 "text" 或空字符串("")而请求状态还是 LOADING readyState (3)时,response 包含到目前为止该请求已经取得的内容。
  • responseText
    在一个请求被发送后,从服务器端返回文本。

    DOMStringXMLHttpRequest 返回的纯文本的值。当 DOMStringnull 时,表示请求失败了。当DOMString 为 "" 时,表示这个请求还没有被 send()
    当处理一个异步 request 的时候,尽管当前请求并没有结束,responseText 的返回值是当前从后端收到的内容。
    当请求状态 readyState变为 XMLHttpRequest.DONE (4),且status值为 200("OK")时,responseText 是全部后端的返回数据
  • responseURL
    只读属性 XMLHttpRequest.responseURL 返回响应的序列化 URL,如果 URL 为空则返回空字符串。如果 URL 有锚点,则位于 URL # 后面的内容会被删除。如果 URL 有重定向,responseURL 的值会是经过多次重定向后的最终 URL。
  • responseXML
    是一个只读值,它返回一个包含请求检索的 HTML 或 XML 的Document,如果请求未成功,尚未发送,或者检索的数据无法正确解析为 XML 或 HTML,则为 null。默认是当作“text / xml”来解析。当 responseType设置为“document”并且请求已异步执行时,响应将被当作“text / html”来解析。responseXML 对于任何其他类型的数据以及 data: URLs为 null。
    备注: responseXML 在这个属性的历史堪称神器,它可以同时在 HTML 和 XML 中工作
    如果服务器没有明确指出 Content-Type 头是 "text/xml" 还是 "application/xml", 你可以使用XMLHttpRequest.overrideMimeType()强制 XMLHttpRequest 解析为 XML。
  • timeout
    是一个无符号长整型数,代表着一个请求在被自动终止前所消耗的毫秒数。默认值为 0,意味着没有超时。超时并不应该用在一个 document environment 中的同步 XMLHttpRequests 请求中,否则将会抛出一个 InvalidAccessError 类型的错误。当超时发生,timeout事件将会被触发。
  • upload
    **XMLHttpRequest.upload **属性返回一个XMLHttpRequestUpload对象,用来表示上传的进度。这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget,可以通过对其绑定事件来追踪它的进度。
事件 相应属性的信息类型
onloadstart 获取开始
onprogress 数据传输进行中
onabort 获取操作终止
onerror 获取失败
onload 获取成功
ontimeout 获取操作在用户规定的时间内未完成
onloadend 获取完成(不论成功与否)
  • channel
    创建请求的时候,XMLHttpRequest.channel 是一个被对象使用的 nsIChannel。如果管道(channel)还没被创建的话,它的值是 null。在一个 multi-part 请求案例中,它是初始化的管道,不是 multi-part 请求中的不同部分。
    需要权限提升。
  • mozAnon
    XMLHttpRequest.mozAnon 是布尔类型。如果这个变量为真,则这次请求将不携带 Cookies 或头部认证信息来发送。
  • mozBackgroundRequest
    备注:(1)Web 内容无法使用此方法。它需要提升权限才能访问。(2)该属性必须在调用 open() 之前设置。
    XMLHttpRequest.mozBackgroundRequest 是一个布尔对象,表示 object 是否为后台的服务请求。如果为 true,则不会将任何加载组与请求关联,并且不会向用户显示安全对话框。
    请求失败时通常会显示安全对话框(例如身份验证或错误证书通知)。
  • mozSystem
    mozSystem 是一个布尔值。如果它被设置为 true,那么在请求时就不会强制要求执行同源策略(Same Origin Policy)。
  • withCredentials
    XMLHttpRequest.withCredentials 属性是一个布尔值,它指示了是否该使用类似 cookie、Authorization 标头或者 TLS 客户端证书等凭据进行跨站点访问控制(Access-Control)请求。设置 withCredentials 对同源请求是无效的。
    备注: 永远不会影响到同源请求。
    备注: 不同域下的 XmlHttpRequest 响应,不论其 Access-Control- 标头设置什么值,都无法为它自身站点设置 Cookie 值,除非它在请求之前将 withCredentials 设为 true。
    此外,这个标志还用于指示何时在响应中忽略 cookie。默认值是 false。除非在发送 XMLHttpRequest 请求之前,将 withCredentials 设置为 true,否则来自不同域的 XMLHttpRequest 响应无法为自己的域设置 cookie 值。而通过设置 withCredentials 为 true 获得第三方 cookie,仍将遵循同源策略,因此请求的脚本无法通过 document.cookie 或者响应标头访问。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容