共计 3917 个字符,预计需要花费 10 分钟才能阅读完成。
旧版 XMLHttpRequest
的缺点
- 只支持文本数据的传输,无法用来读取和上传文件
- 传输和接收数据时,没有进度信息,只能提示有没有完成
XMLHttpRequest
Level2 新功能
- 可以设置 HTTP 请求的时限
- 可以使用 FormData 对象管理表单数据
- 可以上传文件
- 可以获得数据传输的进度信息
设置HTTP请求时限
有时,Ajax 操作很耗时,而且无法预知要耗费多长时间;如果用户网速很慢,可能要等很久;新版本的 XMLTttpRequest 对象,增加了 timeout
属性,可以设置 HTTP 请求的时限:
xhr.timeout = 3000
上面的语句,将最长等待时间设置为 3000 毫秒,超过了这个时限,就会自动停止 HTTP 请求;与之配套的还有一个 ontimeout
事件,用来指定回调函数:
xhr.ontimeout = function(e) { | |
alert('请求超时!') | |
} |
FormData
对象管理表单数据
AJax操作往往用来提交表单数据,为了方便表单处理,HTML5新增了FormData对象,可以模拟表单操作:
// 获取表单元素 | |
var form = document.querySelector('#form1') | |
// 监听表单元素的 submit 事件 | |
form.addEventListener('submit', function (e) { | |
// 阻止默认提交行为 | |
e.preventDefault() | |
// 根据form表单创建 FormData 对象,会自动将表单数据填充到 FormData对象中 | |
var fd = new FormData(form) | |
var xhr = new XMLHttpRequest() | |
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata') | |
xhr.send(fd) | |
xhr.onreadystatechange = function () { | |
if (xhr.readyState === 4 && xhr.status === 200) { | |
console.log(JSON.parse(xhr.responseText)) | |
} | |
} | |
}) |
上传文件
- 定义 UI 结构
- 验证是否选择了文件
// 获取上传文件的按钮 | |
var btnUpload = document.querySelector('#btnUpload') | |
// 为按钮添加 click 事件监听 | |
btnUpload.addEventListener('click', function() { | |
// 获取到文件列表 | |
var files = document.querySelector('#filel').files | |
if(flies.length <= 0 ) { | |
return alert('请选择要上传的文件') | |
} | |
// ...后续业务逻辑 | |
}) |
- 向 FormData中追加文件
// 创建 FormData 对象 | |
var fd = new FormData() | |
// 向 FormData 中追加文件 | |
fd.append('avatar', files[0]) |
- 使用 xhr 发起带文件的请求
// 创建xhr对象 | |
var xhr = new XMLHttpRequest() | |
// 调用open函数,指定请求类型与URL地址;其中请求类型必须为POST | |
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar') | |
// 发起请求 | |
xhr.send(fd) |
- 监听
onreadystatechange
事件
xhr.onreadystatechange = function() { | |
if(xhr.readyState === 4 && xhr.status === 200) { | |
var data = JSON.parse(xhr.responseText) | |
if(data.status === 200) { | |
// 文件上传成功 | |
// 将服务器返回的图片地址,设置为<img>的 src 属性 | |
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url | |
} else { | |
// 图片上传失败 | |
alert('图片上传失败: '+ data.message) | |
} | |
} | |
} |
// 获取上传文件的按钮 | |
var btnUpload = document.querySelector('#btnUpload') | |
// 为按钮添加 click 事件监听 | |
btnUpload.addEventListener('click', function() { | |
// 获取到文件列表 | |
var files = document.querySelector('#filel').files | |
if(flies.length <= 0 ) { | |
return alert('请选择要上传的文件') | |
} | |
// 创建 FormData 对象 | |
var fd = new FormData() | |
// 向 FormData 中追加文件 | |
fd.append('avatar', files[0]) | |
// 创建xhr对象 | |
var xhr = new XMLHttpRequest() | |
// 调用open函数,指定请求类型与URL地址;其中请求类型必须为POST | |
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar') | |
// 发起请求 | |
xhr.send(fd) | |
xhr.onreadystatechange = function() { | |
if(xhr.readyState === 4 && xhr.status === 200) { | |
var data = JSON.parse(xhr.responseText) | |
if(data.status === 200) { | |
// 文件上传成功 | |
// 将服务器返回的图片地址,设置为<img>的 src 属性 | |
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url | |
} else { | |
// 图片上传失败 | |
alert('图片上传失败: '+ data.message) | |
} | |
} | |
} | |
}) |
显示文件上传进度
新版本的 XMLHttpRequest
对象中,可以通过监听 xhr.upload.onprogress
事件,来获取到文件的上传进度
// 创建 xhr 对象 | |
var xhr = new XMLHttpRequest() | |
// 监听 xhr.upload 的 onprogress 事件 | |
xhr.upload.onprogress = function(e) { | |
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度 | |
if(e.lengthComputable) { | |
// e.loaded 以传输字节 | |
// e.total 需传输的总字节 | |
var percentComplete = Math.cell((e.loaded / e.total) * 100) | |
} | |
} |
监听上传完成的事件
xhr.upload.onload = function() { | |
// 移除上传中的类样式 | |
// 添加上传完成的类样式 | |
$('#percent').removeClass().addClass('progress-bar progress-bar-success progress-bar-striped active') | |
} |
使用 jQuery 完成文件上传
ajaxStart(callback)
Ajax请求开始时,执行 ajaxStart
函数; 可以在 ajaxStar
的callback中显示loading效果:
// 自 jQuery 版本 1.8起, 该方法只能被附加到文档上 | |
$(document).ajaxStart(function() { | |
$('#loading').show() | |
}) |
$(document).ajaxStart()
函数会监听当前文档内所有的Ajax请求
ajaxStop(callback)
Ajax请求结束时,执行 ajaxStop
函数; 可以在 ajaxStar
的callback中隐藏loading效果:
// 自 jQuery 版本 1.8起, 该方法只能被附加到文档上 | |
$(document).ajaxStop(function() { | |
$('#loading').hide() | |
}) |
$(function () { | |
// 监听到Ajax请求被发起了 | |
$(document).ajaxStart(function () { | |
$('#loading').show() | |
}) | |
// 监听到Ajax完成的事件 | |
$(document).ajaxStop(function () { | |
$('#loading').hide() | |
}) | |
$('#btnUpload').on('click', function () { | |
// 将 jQuery 对象转换为 DOM 对象,并获取选中文件列表 | |
var files = $('#file')[0].files | |
// 判断是否选择了文件 | |
if (files.length <= 0) { | |
return alert('请选择文件!') | |
} | |
// 向 FormData 中追加文件 | |
var fd = new FormData() | |
fd.append('avatar', files[0]) | |
$.ajax({ | |
method: 'POST', | |
url: 'http://www.liulongbin.top:3006/api/upload/avatar', | |
data: fd, | |
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值 | |
contentType: false, | |
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器 | |
processData: false, | |
success: function (res) { | |
console.log(res) | |
} | |
}) | |
}) | |
}) |
正文完