#什么是 XMLHttpRequest 对象?

XMLHttpRequest 对象用于在后台与服务器交换数据,能够:

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

所有现代的浏览器都支持 XMLHttpRequest 对象。


#创建 XMLHttpRequest 对象

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

通过一行简单的 JavaScript 代码,我们就可以创建 XMLHttpRequest 对象。

创建 XMLHttpRequest 对象的语法:

xmlhttp = new XMLHttpRequest();

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

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

  
  
兼容所有浏览器的创建XMLHttpRequest 对象的代码
var xmlhttp;
if (window.XMLHttpRequest) {
    // code for IE7+,Firefox,Chrome,Opera,Safari
    xmlhttp = new XMLHttpRequest();
} else {
    // code for IE6,IE5
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
    
    

#XMLHttpRequest对象有多个属性和方法,还有一个事件句柄。
XMLHttpRequest 对象属性和方法
属性 说明
readyState HTTP 请求的状态。当一个 XMLHttpRequest 初次创建时,这个属性的值从 0 开始,直到接收到完整的 HTTP 响应,这个值增加到 4。
取值 描述
0
描述一种"未初始化"状态;此时,已经创建一个XMLHttpRequest对象,但是还没有初始化。
1
描述一种"发送"状态;此时,代码已经调用了XMLHttpRequest open()方法并且XMLHttpRequest已经准备好把一个请求发送到服务器。
2
描述一种"发送"状态;此时,已经通过send()方法把一个请求发送到服务器端,但是还没有收到一个响应。
3
描述一种"正在接收"状态;此时,已经接收到HTTP响应头部信息,但是消息体部分还没有完全接收结束。
4
描述一种"已加载"状态;此时,响应已经被完全接收。
responseText 从服务器接收到的数据(不包括头部)(解析为一个字符串)。
responseXML 从服务器接收到的数据(不包括头部)(解析为 XML 并作为 Document 对象返回)。
status 由服务器返回的 HTTP 状态代码。如 200 表示成功,404 表示 "Not Found" 错误。
statusText 这个属性用名称而不是数字指定了请求的 HTTP 的状态代码。也就是说,当状态为 200 的时候它是 "OK",当状态为 404 的时候它是 "Not Found"。
事件句柄 onreadystatechange 每次 readyState 属性改变的时候调用的事件句柄函数。
方法 abort() 取消当前响应,关闭连接并且结束任何未完成的网络活动。
getAllResponseHeaders() 把 HTTP 响应头部(所有头部)作为一个字符串返回。
getResponseHeader() 返回指定的 HTTP 响应头部的值,其参数是要返回的 HTTP 响应头部的名称。可以使用任何大小写来制定这个头部名字,和响应头部的比较是不区分大小写的。
open() 初始化 HTTP 请求参数,例如 URL 和 HTTP 方法,但是并不发送请求。
open(method,url,async,username,password)
  • method 参数是用于请求的 HTTP 方法。值包括 GET、POST 、HEAD、PUT、DELETE。
  • url 参数是请求的主体。大多数浏览器实施了一个同源安全策略,并且要求这个 URL 与包含脚本的文本具有相同的主机名和端口。
  • async 参数指示请求使用应该异步地执行。如果这个参数是 false,请求是同步的,后续对 send() 的调用将阻塞,直到响应完全接收。如果这个参数是 true 或省略,请求是异步的,且通常需要一个 onreadystatechange 事件句柄。
  • username 和 password 参数是可选的,为 url 所需的授权提供认证资格。如果指定了,它们会覆盖 url 自己指定的任何资格。
send() 发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。
send(body)
  • 如果通过调用 open() 指定的 HTTP 方法是 POST 或 PUT,body 参数指定了请求体,作为一个字符串或者Document 对象
  • 如果请求体不是必须的话,这个参数就为 null。对于任何其他方法,这个参数是不可用的,应该为 null(有些实现不允许省略该参数)。
在XHR 2之中,send方法可以发送许多类型的数据。
  • void send();
  • void send(ArrayBuffer data);
  • void send(Blob data);
  • void send(Document data);
  • void send(DOMString data);
  • void send(FormData data);
Blob类型可以用来发送二进制数据,这使得通过Ajax上传文件成为可能。
setRequestHeader() 向一个打开但未发送的请求设置或添加一个 HTTP 请求。
setRequestHeader(name,value)
  • name 参数是要设置的头部的名称。这个参数不应该包括空白、冒号或换行。
  • value 参数是头部的值。这个参数不应该包括换行。

XMLHttpRequest对象用于从JavaScript发出HTTP请求
典型用法:
// 新建一个XMLHttpRequest实例对象
var xhr = new XMLHttpRequest();
// 指定通信过程中状态改变时的回调函数
xhr.onreadystatechange = function() {
    // 通信成功时,状态值为4
    var completed = 4;
    if (xhr.readyState === completed) {
        if (xhr.status === 200) {
            // 处理服务器发送过来的数据
        } else {
            // 处理错误
        }
    }
};
// open方式用于指定HTTP动词、请求的网址、是否异步
xhr.open('GET','__MODULE__/Xhr/index',true);
// 发送HTTP请求
xhr.send(null)

在ThinkPHP框架下的示例:
IndexController.class.PHP
<?PHP 
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index() {
        $this - >display();
    }
}
View/Index/index.html
<!DOCTYPE html>
<html>
 <head> 
  <title>Xml_HTTP_Request</title> 
  <Meta http-equiv="Content-Type" content="text/html;charset=utf8" /> 
 </head> 
 <body>
   Xml_HTTP_Request测试页面
 </body>
</html>
<script>
// 新建一个XMLHttpRequest实例对象
var xhr = new XMLHttpRequest();
// 指定通信过程中状态改变时的回调函数
xhr.onreadystatechange = function() {
    var completed = 4; // 通信成功时,状态值为4
    if (xhr.readyState === completed) {
        // 处理服务器发送过来的数据
        if (xhr.status === 200) {
            alert(xhr.responseText);
        }
        // 处理错误
        else {
            alert(xhr.statusText);
        }
    }
};
// open方式用于指定HTTP动词、请求的网址、是否异步
xhr.open('GET',true);
// 发送HTTP请求
xhr.send(null); 
</script>
 
XhrController.class.PHP
<?PHP 
namespace Home\Controller;
use Think\Controller;
class XhrController extends Controller {
    public function index() {
        echo 'This is responseText!';
    }
}
数据流:

数据流方式就是在建立的连接断开之前,也就是 readystate 状态为 3 的时候接受数据。麻烦的事情也在这里,因为数据正在传输,你拿到的 xhr.response 可能就是半截数据,所以呢,最好定义一个数据传输的协议,比如前2个字节表示字符串的长度,然后你只获取这个长度的内容,接着改变游标的位置。

假如数据格式为: data splitChar(data为数据内容;splitChar为数据结束标志,长度为1)。

那么传输的数据内容为 data splitChar data splitChar data splitChar...

var dataStream = function(type,url) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        // 状态为 3,数据接收中
        if (xhr.readyState == 3) {
            var i,l,s;
            s = xhr.response; //读取数据
            l = s.length; //获取数据长度
            //从游标位置开始获取数据,并分割数据
            s = s.slice(p,l - 1).split(splitChar);
            //循环并操作数据
            for (i in s) if (s[i]) deal(s[i]);

            //更新游标位置
            p = l;
        }
        // 状态为 4,数据传输完毕,重新连接
        if (xhr.readyState == 4) {
            xhr.onreadystatechange = null;
            dataStream(type,url);
        }
    };
    xhr.open(type,true);
    xhr.send();
};

这个代码写的是存在问题的,当 readystate 为 3 的时候可以获取数据,但是这时获取的数据可能只是整体数据的一部分,那后半截就拿不到了。但 readystate 在数据传输完毕之前是不会改变的,也就是说并不会继续接受剩下的数据。我们可以定时去监听readystate。这样的处理不算复杂,但是低版本IE不允许在readystate为3的时候读取数据,所以我们必须利用iframe照样可以异步获取数据,对于低版本IE可以使用iframe来接受数据流。

if (isIE) {
    var dataStream = function(url) {
        var ifr = document.createElement("iframe"),doc,timer;
        ifr.src = url;
        document.body.appendChild(ifr);
        doc = ifr.contentwindow.document;
        timer = setInterval(function() {
            if (ifr.readyState == "interactive") {
                // 处理数据,同上
            }
            // 重新建立链接
            if (ifr.readyState == "complete") {
                clearInterval(timer);
                dataStream(url);
            }
        },16);
    };
};

定时去监听iframe的readystate的变化,从而获取数据流。不过还是存在问题。数据流实现“服务器推”数据的原理是就是文档(数据)还没有加载完,浏览器去服务器拿数据完成文档(数据)加载,我们就是利用这点,给浏览器塞点东西过去。

所以上述利用iframe的方式获取数据,会使浏览器一直处于加载状态,title上的那个圈圈一直在转动,鼠标的状态也是loading,这看着是相当不爽的。幸好,IE提供了HTMLFile对象,这个对象就相当于一个内存中的Document对象,它会解析文档。所以我们创建一个HTMLFile对象,在里面放置一个IFRAME来连接服务器。这样,各种浏览器就都支持了。

if (isIE) {
    var dataStream = function(url) {
        var doc = new ActiveXObject("HTMLFile"),ifr = doc.createElement("iframe"),timer,d;
        doc.write("<body/>");
        ifr.src = url;
        doc.body.appendChild(ifr);
        d = ifr.contentwindow.document;
        timer = setInterval(function() {
            if (d.readyState == "interactive") {
                // 处理数据,同上
            }
            // 重新建立链接
            if (d.readyState == "complete") {
                clearInterval(timer);
                dataStream(url);
            }
        },16);
    };
};

#FormData类型可以用于构造表单数据
比起普通的Ajax,使用FormData的最大优点就是可以 异步上传一个二进制文件

构造方法:
new FormData(optional HTMLFormelement form)
参数:可选,是一个表单元素,可以包含任何形式的表单控件

给当前FormData对象添加一个键值对:
  • void append(DOMString name,Blob value,optional DOMString filename)
  • void append(DOMString name,DOMString value)
参数:
  • name,字段名称
  • value,字段值
  • filename,可选,指定文件的文档名(当value被指定为一个Blob对象或者File对象时)
示例:
var formData = new FormData();
formData.append('username','张三');
formData.append('email','zhangsan@example.com');
formData.append('birthDate',1940);
xhr.send(formData);
上面这段代码和下面这段的效果是一样的:
<html>
 <head></head>
 <body>
  <form id="registration" name="registration" action="/register"> 
   <input type="text" name="username" value="张三" /> 
   <input type="email" name="email" value="zhangsan@example.com" /> 
   <input type="number" name="birthDate" value="1940" /> 
   <input type="submit" onclick="return sendForm(this.form);" /> 
  </form>
 </body>
</html>
FormData对象还可以对现有的表单添加数据
function sendForm(form) {
    var formData = new FormData(form);
    formData.append('csrf','e69a18d7db1286040586e6da1950128');
    var xhr = new XMLHttpRequest();
    xhr.open('POST',form.action,true);
    xhr.onload = function(e) {
        //...
    };
    xhr.send(formData);
    return false;
}
var form = document.querySelector('#registration');
sendForm(form);
FormData对象也能模拟File控件,进行文件上传
var oMyForm = new FormData();
oMyForm.append("username","Groucho");
oMyForm.append("accountnum",123456);
// fileInputElement中已经包含了用户所选择的文件
oMyForm.append("userfile",fileInputElement.files[0]);
var oFileBody = "<a id="a "><b id="b ">hey!</b></a>"; // Blob对象包含的文件内容
var oBlob = new Blob([oFileBody],{
    type: "text/xml"
});
oMyForm.append("webmasterfile",oBlob);
var oReq = new XMLHttpRequest();
oReq.open("POST","http://foo.com/submitform.PHP");
oReq.send(oMyForm);

XMLHttpRequest和 FormData实现Ajax的更多相关文章

  1. 详解Html5页面实现下载文件(apk、txt等)的三种方式

    这篇文章主要介绍了详解Html5页面实现下载文件(apk、txt等)的三种方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. 基于HTML十秒做出淘宝页面

    十分钟做出一个网页,看似不可思议,下面小编给大家带来了基于HTML十秒做出淘宝页面,只分为两步,代码超级简单,需要的朋友参考下吧

  4. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. 跨域修改iframe页面内容详解

    这篇文章主要介绍了跨域修改iframe页面内容详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. 使用postMessage让 iframe自适应高度的方法示例

    这篇文章主要介绍了使用postMessage让 iframe自适应高度的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. 通过AFNetworking 2.0上传iOS图像

    我一直在寻找新的AFNetworking2.0上传图像的例子.但是我正在撞墙,无法弄清楚代码有什么问题.所以这是我使用的代码TIA解决方法我最终使用了多部分请求

  8. ios – 在Objective-C中发送分块的HTTP 1.1请求

    我有以下问题:我正在创建一个非常大的SOAP请求(数据是一个编码为Base64字符串的视频),因此我不能将其作为原始SOAP请求发送,而是需要在HTTP1.1块中发送它.我似乎无法弄明白该怎么做.我在这里使用了代码:WhatarealternativestoNSURLConnectionforchunkedtransferencoding但它似乎没有做我认为应该做的事情–我可以看到请求作为单个请求

  9. ios – Cordova 3.7在每个本机通话中复制iframe

    由于我已升级到Cordova3.7,每个本地调用都将一个新的iframe附加到DOM,如下所示.为了排除我现有的代码影响cordova的可能性,我尝试使用cordovaCLI创建一个新的代码,添加控制台插件,并在设备控制台中的setInterval循环中调用console.log().因此,我在DOM中收到了大量的iframe.我在iPad3,iOS7上尝试过使用xCode6构建应用程序.有没有人遇到这个问题?

  10. ios – Swift2.0 HTTP请求无法正常工作

    参见英文答案>TransportsecurityhasblockedacleartextHTTP23个HelloStackoverflow,我将swift应用程序移动到Swift2.0后,我不断收到此错误:我看了下面的链接https://forums.developer.apple.com/thread/5835并将以下代码添加到我的info.plist中它仍然不起作用,任何人都有替代解决方案?解

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部