基础系列-ajax与fetch
AJAX
概念
Asynchronous JavaScript + XML(异步JavaScript和XML), 其本身不是一种新技术,而是一个在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合的‘新’方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的 XMLHttpRequest
。当使用结合了这些技术的AJAX模型以后, 网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。
请求的数据格式
设置 Content-Type 实体头部用于指示资源的MIME类型
text/html:请求 Web ⻚面时返回响应的类型,Body 中返回 html 文本。
application/json:常用,复杂的数据结构。
multipart/form-data:提交文件、非 ASCII 码的数据或者是二进制流数据。
application/x-www-form-urlencoded:form表单默认编码方式。
XMLHttpRequest
概念
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest
在 AJAX 编程中被大量使用。
XMLHttpRequest
可以用于获取任何类型的数据,而不仅仅是 XML。它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制。
属性和方法
属性
- upload:(只读)上传进度。
- status:(只读)代表请求响应状态。返回一个无符号短整型数字。
- readyState:(只读)代表请求的状态码。
- 0 - UNSENT - 代理被创建,但尚未调用 open() 方法
- 1 - OPENED - open() 方法已经被调用
- 2 - HEADERS_RECEIVED - send() 方法已经被调用,并且头部和状态已经可获得
- 3 - LOADING - 下载中;responseText 属性已经包含部分数据
- 4 - DONE - 下载操作已完成
- response:(只读)包含整个响应实体。返回一个
ArrayBuffer
、Blob
、Document
,或DOMString
,具体是哪种类型取决于XMLHttpRequest.responseType
的值。 - responseText:(只读)返回一个
DOMString
,该DOMString
包含对请求的响应,如果请求未成功或尚未发送,则返回null
。 - responseType:一个用于定义响应类型的枚举值。
- responseURL:(只读)返回经过序列化(serialized)的响应 URL,如果该 URL 为空,则返回空字符串。
- responseXML:(只读)返回一个
Document
,其中包含该请求的响应,如果请求未成功、尚未发送或时不能被解析为 XML 或 HTML,则返回null
。 - statusText:(只读)返回一个
DOMString
,其中包含 HTTP 服务器返回的响应状态。与XMLHTTPRequest.status
不同的是,它包含完整的响应状态文本(例如,”200 OK
“)。 - timeout:超时时长。
- ontimeout:设置一个函数处理超时问题。
- withCredentials:一个布尔值,用来指定跨域
Access-Control
请求是否应当带有授权信息,如 cookie 或授权 header 头。
方法
.abort()
:如果请求已被发出,则立刻中止请求。.getAllResponseHeaders()
:以字符串的形式返回所有用 CRLF 分隔的响应头,如果没有收到响应,则返回null
。.getResponseHeader()
:返回包含指定响应头的字符串,如果响应尚未收到或响应中不存在该报头,则返回null
。.open()
:初始化一个请求。.overrideMimeType()
:覆写由服务器返回的 MIME 类型。.send()
:发送请求。如果请求是异步的(默认),那么该方法将在请求发送后立即返回。.setRequestHeader()
:设置 HTTP 请求头的值。必须在open()
之后、send()
之前调用setRequestHeader()
方法。
事件
使用 xhr.addEventListener 的方式添加监听事件,或使用on-*属性进行设置监听
abort:可以设置监听 abort() 方法调用。
error:错误时触发。
progress:当请求接受到更多数据时,周期性地触发。
load:请求成功完成时触发。
loadend:当请求结束时触发,无论成功还是失败。
loadstart:接受到响应数据时触发。
timeout:在预设时间内没有接受到响应时触发。
实战
function request(data === null) {
if (!data) {
return
}
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
// 请求操作已完成
if (xhr.readyState == 4)) {
// 判断响应状态
if (xhr.status.toString().startsWith('2') || xhr.status === 304) {
// 获取返回结果
const res = xhr.response
console.log(res)
} else {
console.error('error: ', xhr.status)
}
}
}
// 初始化一个请求,第三个参数设置异步请求还是同步请求,默认值为false为异步请求
xhr.open('GET', 'url.action')
// 出错时处理
xhr.onerror = function () {
console.log("An error occurred during the transaction");
};
// 必须在 open 之后,send之前设置 header
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
// 设置超时
xhr.timeout = 10000 // 设置 10 秒超时
xhr.ontimeout = function() {
console.log("Request did not return in a second.")
}
// 发送请求
xhr.send(data)
}
promise 改造
function request(formData = null) {
if (!formData) {
return
}
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function() {
// 请求操作已完成
if (xhr.readyState === 4) {
// 判断响应状态
if (xhr.status.toString().startsWith('2') || xhr.status === 304) {
// 获取返回结果
const res = xhr.response
resolve(res)
} else {
reject(xhr.status)
}
}
}
// 初始化一个请求,第三个参数设置异步请求还是同步请求,默认值为false为异步请求
xhr.open(formData.method, formData.url)
// 必须在 open 之后,send之前设置 header
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
// 设置超时
xhr.timeout = 10000 // 设置 10 秒超时
xhr.ontimeout = function() {
console.log("Request did not return in a second.")
}
// 发送请求
xhr.send(formData.data || null)
})
}
// 使用
request({
method: 'GET',
url: 'www.baidu.com',
data: null,
}).then(res => console.log(res)).catch(err => console.error(err))
Fetch
相对于 XMLHttpRequest 相同的功能,但更具有可扩展性和高效性。
Fetch API 提供了一个获取资源的接口(包括跨域请求)。且基于 Promise。
核心
Fetch 的核心在于对 HTTP 接口的抽象,包括 Request
,Response
,Headers
,Body
,以及用于初始化异步请求的 global fetch
。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。
Guard
Guard 是 Headers
对象的特性,基于不同的情况,它可以有以下取值:immutable
、request
、request-no-cors
、response
或 none
。
头信息的 guard 会影响 set()
、delete()
和 append()
方法。
实战
var myImage = document.querySelector('img');
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg');
fetch(myRequest,myInit).then(function(response) {
...
});
// 或
var myInit = { method: 'GET',
headers: {
'Content-Type': 'image/jpeg'
},
mode: 'cors',
cache: 'default' };
var myRequest = new Request('flowers.jpg', myInit);