XMLHttpRequest,FormData对象和Promise封装

之前在项目中看到过一段上传文件的代码,其中有这样一句:

const form = new FormData();

当时不知道这个FormData()是个什么东西,好像也没有这样的构造函数,但是用的时候都是复制粘贴的,代码也能正常运行,所以也就没有多想。

今天无意中查了一下XMLHttpRequest,原来这玩意还有Level 1标准和Level 2标准,我知道的那些都是Level 1,而FormData是Level 2里面的新增特性,下面就来系统总结一下。

什么是 XMLHttpRequest 对象

以下内容引用自W3School:

XMLHttpRequest 对象用于在后台与服务器交换数据。

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

如何创建 XMLHttpRequest 对象

这里回顾一下Level 1的用法。

首先,新建一个XMLHttpRequest的实例。

var xhr= new XMLHttpRequest();

然后,向远程主机发出一个HTTP请求。这里的第三个参数Async规定请求是否异步处理,true或者不传都表示脚本会在 send() 方法之后继续执行,而不等待来自服务器的响应。也就是说,send()这句是异步的。

xhr.open("GET", "https://www.xiaomizhou.com", true);
xhr.send();

接着,就等待远程主机做出回应。这时需要监控XMLHttpRequest对象的状态变化,指定回调函数。

xhr.onreadystatechange = function () {
    if (request.readyState === 4 && request.status === 200) {
        console.log(request.responseText)
    }
}

XMLHttpRequest对象的主要属性

xhr.readyState:XMLHttpRequest对象的状态,一共有5种状态
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了

xhr.status:服务器返回的状态码,等同于HTTP的状态
200:请求成功
400: 内部服务器错误

xhr.responseText:服务器返回的文本数据

xhr.responseXML:服务器返回的XML格式的数据

xhr.statusText:服务器返回的状态文本

request.onload = function(e){} 请求成功

request.process = function(e){} 请求正在加载

request.onerror = function(e){} 请求失败

老版本的缺点

老版本的XMLHttpRequest对象有以下几个缺点:

1. 只支持文本数据的传送,无法用来读取和上传二进制文件。
2. 传送和接收数据时,没有进度信息,只能提示有没有完成。
3. 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。

新版本的功能

新版本的XMLHttpRequest对象,针对老版本的缺点,做出了大幅改进。

1. 设置HTTP请求的时限

新版本的XMLHttpRequest对象,增加了timeout属性。下面的语句,将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。

xhr.timeout = 3000;

与之配套的还有一个timeout事件,用来指定回调函数。

xhr.ontimeout = function(event){
	alert('请求超时!');
}

2. FormData对象

ajax操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个FormData对象,可以模拟表单。

首先,新建一个FormData对象。

var formData = new FormData();

然后,为它添加表单项。

formData.append('username', '张三');
formData.append('id', 123456);

最后,直接传送这个FormData对象。这与提交网页表单的效果,完全一样。

xhr.send(formData);

FormData对象也可以用来获取网页表单的值。

var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一个表单项
xhr.open('POST', form.action);
xhr.send(formData);

FormData对象最大的作用是上传文件。假定files是一个"选择文件"的表单元素(input[type=“file”]),我们将它装入FormData对象。

var formData = new FormData();
for (var i = 0; i < files.length;i++) {
	formData.append('files[]', files[i]);
}

然后,发送这个FormData对象。

xhr.send(formData);

3. 跨域资源共享(CORS)

新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。

使用"跨域资源共享"的前提,是浏览器必须支持这个功能,而且服务器端必须同意这种"跨域"。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样。

xhr.open('GET', 'http://other.server/and/path/to/script');

4. 进度信息

新版本的XMLHttpRequest对象,传送数据的时候,有一个progress事件,用来返回进度信息。

它分成上传和下载两种情况。下载的progress事件属于XMLHttpRequest对象,上传的progress事件属于XMLHttpRequest.upload对象。

首先,定义事件的回调函数。

xhr.onprogress = updateProgress; // 下载事件的回调
xhr.upload.onprogress = updateProgress; // 上传事件的回调

然后,在回调函数里面。使用这个事件的一些属性。

function updateProgress(event) {
	if(event.lengthComputable) {
		var percentComplete = event.loaded / event.total;
	}
}

上面的代码中,event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0。

与progress事件相关的。还有其他5个事件,可以分别指定回调函数。

load:传输成功完成。
abort:传输被用户取消。
error:传输中出现错误。
loadstart:传输开始。
loadEnd:传输结束,但不知道成功还是失败。

Promise封装ajax请求

下面代码中,getJSON是对 XMLHttpRequest 对象的封装,用于发出一个针对 JSON 数据的 HTTP 请求,并且返回一个Promise对象。

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

参考:
XMLHttpRequest 详解
XMLHttpRequest Level 2 使用指南 - 阮一峰
Promise对象 - 阮一峰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值