XHR 是什么?

本文详细介绍了XMLHttpRequest对象,它是实现AJAX功能的基础。解释了如何创建和使用XMLHttpRequest对象,包括发送GET和POST请求的方法,以及如何处理响应。还讨论了跨域请求的问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就是 XMLHttpRequest 对象。

也就是ajax功能实现所依赖的对象

相关资料: http://www.w3school.com.cn/xml/xml_http.asp


可能很多人比较熟悉 query中的 ajax函数,没怎么在意 XHR 这个名词,jquery中的ajax就是对 xhr的封装。

下面简单说说这个比较原始的XMLHttpRequest对象。

XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。XHR接口强制要求每个请求都具备严格的HTTP语义–应用提供数据和URL,浏览器格式化请求并管理每个连接的完整生命周期,所以XHR仅仅允许应用自定义一些HTTP首部,但更多的首部是不能自己设定的,如:

  • Accept-Charset, Accept-Encoding, Access-Control-*
  • Host, Upgrade, Connection, Referer, Origin
  • Cookie, Sec-, Proxy-, 及其他首部

浏览器会拒绝绝对不安全的首部重写,以保证应用不能假扮用户代理、用户或请求来源,如Origin由浏览器自动设置,Access-Control-Allow-Origin由服务器设置,如果接受该请求,不包含该字段即可,浏览器发出的请求将作废。

  • CORS请求会省略cookie和HTTP认证等用户凭据;
  • 客户端被限制只能发送“简单的跨域请求”,包括只能使用GET POSD HEAD三种方式,只能访问通过XHR发送并读取的HTTP首部。

如果想要启用cookie和HTTP认证,客户端必须在发送请求时通过XHR对象发送额外的属性(withCredentials),而服务器也需要以Access-Control-Allow-Credentials响应,表示允许应用发送隐私数据。同样,如果客户需要写入或读取自定义HTTP标头或想要使用“非简单的方法”的请求,那么它必须首先通过发出一个预备请求,以获取第三方服务器的许可,如下所示:

Http请求交互的报文如下 

// Preflight request
OPTIONS /resource.js HTTP/1.1
Host: thirdparty.com
Origin: http://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: My-Custom-Header
...
 
// Preflight response
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: My-Custom-Header
...
 
(actual HTTP request)

W3C CORS规范定义的什么时候必须使用预备请求,“简单”的请求可以跳过它,但也有各种各样场景需要使用预备请求,这就添加一次往返网络延迟。可喜的是,一旦预备请求完成,它可以由客户端缓存,以避免在后续请求进行相同的验证。 
在XHR中,可以通过responseType-设置改变响应类型,如下所示:

  • “” 字符串(默认值)
  • “arraybuffer” ArrayBuffer
  • “blob” Blob
  • “document” Document
  • “json” JavaScript 对象,解析自服务器传递回来的JSON 字符串。
  • “text” 字符串

下面是个小案例

//类的构建定义,主要职责就是新建XMLHttpRequest对象  
var MyXMLHttpRequest=function(){  
    var xmlhttprequest;  
    if(window.XMLHttpRequest){  
        xmlhttprequest=new XMLHttpRequest();  
        if(xmlhttprequest.overrideMimeType){  
            xmlhttprequest.overrideMimeType("text/xml");  
        }  
    }else if(window.ActiveXObject){  
        var activeName=["MSXML2.XMLHTTP","Microsoft.XMLHTTP"];  
        for(var i=0;i<activeName.length;i++){  
            try{  
                xmlhttprequest=new ActiveXObject(activeName[i]);  
                break;  
            }catch(e){  
                         
            }  
        }  
    }  
      
    if(xmlhttprequest == undefined || xmlhttprequest == null){  
        alert("XMLHttpRequest对象创建失败!!");  
    }else{  
        this.xmlhttp=xmlhttprequest;  
    }  
      
    //用户发送请求的方法  
    MyXMLHttpRequest.prototype.send=function(method,url,data,callback,failback){  
        if(this.xmlhttp!=undefined && this.xmlhttp!=null){  
            method=method.toUpperCase();  
            if(method!="GET" && method!="POST"){  
                alert("HTTP的请求方法必须为GET或POST!!!");  
                return;  
            }  
            if(url==null || url==undefined){  
                alert("HTTP的请求地址必须设置!");  
                return ;  
            }  
            var tempxmlhttp=this.xmlhttp;  
            this.xmlhttp.onreadystatechange=function(){  
                if(tempxmlhttp.readyState==4){  
                    if(temxmlhttp.status==200){  
                        var responseText=temxmlhttp.responseText;  
                        var responseXML=temxmlhttp.reponseXML;  
                        if(callback==undefined || callback==null){  
                            alert("没有设置处理数据正确返回的方法");  
                            alert("返回的数据:" + responseText);  
                        }else{  
                            callback(responseText,responseXML);  
                        }  
                    }else{  
                        if(failback==undefined ||failback==null){  
                            alert("没有设置处理数据返回失败的处理方法!");  
                            alert("HTTP的响应码:" + tempxmlhttp.status + ",响应码的文本信息:" + tempxmlhttp.statusText);  
                        }else{  
                            failback(tempxmlhttp.status,tempxmlhttp.statusText);  
                        }  
                    }  
                }  
            }  
              
            //解决缓存的转换  
            if(url.indexOf("?")>=0){  
                url=url + "&t=" + (new Date()).valueOf();  
            }else{  
                url=url+"?+="+(new Date()).valueOf();  
            }  
              
            //解决跨域的问题  
            if(url.indexOf("http://")>=0){  
                url.replace("?","&");  
                url="Proxy?url=" +url;  
            }  
            this.xmlhttp.open(method,url,true);  
              
            //如果是POST方式,需要设置请求头  
            if(method=="POST"){  
                this.xmlhttp.setRequestHeader("Content-type","application/x-www-four-urlencoded");  
            }  
            this.xmlhttp.send(data);  
    }else{  
        alert("XMLHttpRequest对象创建失败,无法发送数据!");  
    }  
    MyXMLHttpRequest.prototype.abort=function(){  
        this.xmlhttp.abort();  
    }  
  }  
}  



<think>好的,我现在需要弄清楚HTTP是属于XHR(XMLHttpRequest)还是Fetch。首先,我得明确这几个术语各自的定义和它们之间的关系。 首先,HTTP,即超文本传输协议,是用于传输超媒体文档(如HTML)的应用层协议。它是Web数据通信的基础,客户端(比如浏览器)通过HTTP向服务器发送请求,服务器则返回响应。所以HTTP本身是一个协议,和XHR、Fetch不在同一个分类层级上。 接下来,XHR和Fetch都是浏览器提供的API,允许客户端与服务器进行HTTP通信。XHR是较早的技术,最初由微软引入,后来被其他浏览器采纳。它允许在不重新加载页面的情况下更新部分页面内容,也就是常说的AJAX。使用XHR可以发送各种HTTP请求(GET、POST等),并处理响应。不过,XHR的API设计相对老旧,使用回调函数,可能会导致回调地狱,而且对Promise的支持需要额外处理。 然后是Fetch API,这是较新的标准,旨在替代XHR。它基于Promise,提供了更简洁和强大的方式来处理HTTP请求。Fetch API设计更现代化,支持流和其他高级功能,但使用时需要注意错误处理(比如HTTP 404不会被reject)以及需要手动处理JSON转换等。 现在,问题在于HTTP属于哪一个。其实,HTTP作为协议,XHR和Fetch都是使用该协议进行通信的手段。所以应该说,XHR和Fetch都是基于HTTP协议的API实现,而不是HTTP属于它们中的任何一个。换句话说,两者都是客户端通过HTTP与服务器交互的工具,但HTTP本身是独立存在的协议,不属于任何一个API。 不过,用户的问题可能是在混淆概念,需要明确它们之间的关系。可能需要进一步验证是否正确,比如查阅文档确认XHR和Fetch的作用,以及HTTP的定位。确认后,答案应该是HTTP既不属于XHR也不属于Fetch,而是它们两者都依赖于HTTP协议来实现客户端与服务器的通信。</think>HTTP **不属于** XHR(XMLHttpRequest)或 Fetch,而是它们两者都基于HTTP协议进行通信。以下是逐步解释: --- ### **1. 基本概念区分** - **HTTP**(超文本传输协议): 是一种用于传输超媒体文档(如HTML)的**应用层协议**。它定义了客户端(如浏览器)与服务器之间请求和响应的格式。 - **XHR(XMLHttpRequest)**: 是浏览器提供的**API**,允许通过JavaScript发送HTTP请求并接收响应,常用于实现AJAX(异步通信)。 - **Fetch API**: 是浏览器提供的**现代API**,同样用于发送HTTP请求,但基于Promise设计,语法更简洁,功能更强大。 --- ### **2. 关系分析** - **XHR和Fetch是工具,HTTP是协议**: - XHR和Fetch都使用HTTP协议与服务器通信。 - 它们本质上是**客户端(浏览器)调用HTTP协议的具体实现方式**。 - **类比理解**: - 如果将HTTP比作“语言”,XHR和Fetch就是“说话的方式”。 - 例如:HTTP定义了如何“问问题”和“回答问题”,而XHR/Fetch是具体“提问”的工具。 --- ### **3. 核心区别** | 特性 | XHR | Fetch API | |---------------------|------------------------------|-------------------------------| | **设计时代** | 早期标准(2006年) | 现代标准(2015年引入) | | **语法** | 基于回调函数,代码冗余 | 基于Promise,链式调用更简洁 | | **错误处理** | 通过`onerror`事件捕获错误 | 需手动检查`response.ok` | | **流式数据处理** | 不支持 | 支持`Response.body`流式读取 | | **跨域请求** | 需手动设置`withCredentials` | 通过`credentials: 'include'`设置 | --- ### **4. 代码示例** - **XHR发送GET请求**: ```javascript const xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.example.com/data'); xhr.onload = function() { if (xhr.status === 200) console.log(xhr.responseText); }; xhr.send(); ``` - **Fetch发送GET请求**: ```javascript fetch('https://api.example.com/data') .then(response => { if (!response.ok) throw new Error('请求失败'); return response.json(); }) .then(data => console.log(data)) .catch(error => console.error(error)); ``` --- ### **5. 总结** - **HTTP**是协议,XHR和Fetch是基于HTTP的API实现。 - **XHR**是旧方案,**Fetch**是新标准,两者功能相似但语法和特性不同。 - 推荐优先使用**Fetch API**(除非需兼容旧浏览器)。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值