1. 简介
- Ajax全称Asynchronous Javascript And XML(即异步的javascript和XML),它是现代大多数web应用程序做为数据交互的核心技术,它支持在页面不刷新的前提下,向web服务器异步的发送数据请求和接收,从而实现页面无刷新显示新的数据,提升交互体验。Ajax不是一种新的编程语言或者某一种技术,而是一个概念,是一种应用客户端脚本加载服务器数据的方法。
- Fetch是一个现代的概念, 等同于XMLHttpRequest,它提供了许多与XMLHttpRequest相同的功能。被称为下一代Ajax技术,它采用Promise方式来处理数据,是一种简洁明了的API,比XMLHttpRequest更加简单易用。
2. 详解Ajax
实现Ajax的核心方法是使用XMLHttpRequest(XHR)对象,XHR对象用于服务器交互,通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。
XMLHttpRequest技术在1998年前后得到了应用,并在1999年首页作为非标准的Inter Explorer5.0 ActiveX组件出现,是微软开发用来支持基于浏览器的Outlook版本,XML是当时最流行的数据格式。
Ajax是2005年Jesse James Garrett在他的文章《AJAX:web应用程序方法》中提出的新术语,用来描述一种使用现有技术集合的方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。
- ajax示例
// 创建XMLHttpRequest对象xhr
var xhr = new XMLHttpRequest()
// 设置xhr请求超时时间
xhr.timeout = 3000
// 设置响应数据格式
xhr.reponseType = 'JSON'
// 创建一个GET请求
xhr.open('GET','/server',true)
xhr.onload = function(e){
if(this.status === 200 || this.status === 304){
// 数据处理逻辑
console.log(xhr.responseText)
}
}
// xhr相关事件注册及回调
xhr.ontimeout = functioin(e){...}
xhr.onerror = functioin(e){...}
xhr.upload.onprogress = functioin(e){...}
// 发送数据
xhr.send()
XMLHttpRequest API
属性
- onreadystatechange:当readyState属性发生变化时调用的EventHandler
- readyState(只读):对象有以下几种状态 值|状态|描述 --|:--:|-- 0 |UNSENT |对象已经建立,但还没有调用open方法 1 |OPENED |已经调用open的方法,send()方法还未被调用。注意:只有xhr处于OPENED状态,才能调用xhr.setRequestHeader()和xhr.send(),否则会报错 2 |HEADERS_RECEIVED |已经调用open方法,头部信息已经是可用的 3 |LOADING |正在加载,服务器已经返回一些数据 4 |DONE |整个发送和接收数据完成
- response(只读):返回ArrayBuffer、Blob、Document、DOMString,具体是哪种类型取决于XMLHttpRequest.responseType的值。其中包含响应体body
- responseText(只读):返回一个DOMString,该DOMString包含对请求的响应,如果请求未成功或尚未发送,则返回null
- responseType:设置服务器返回的数据类型 值|状态|描述 --|:--:|-- "" |DOMString |对象已经建立,但还没有调用open方法 arraybuffer |ArrayBuffer |已经调用open的方法 blob |Blob |已经调用open方法,头部信息已经是可用的 document |Document |正在加载,服务器已经返回一些数据 json |JSON |整个发送和接收数据完成 text |DOMString |整个发送和接收数据完成
- responseXML:仅当responseType为""、"text"或"document"时可用,类似response,返回响应的Document类型的正文
- responseURL:返回响应的序列化URL,如果URL为空则返回空串。URL不包含锚点#后面的内容。如果有重定向,返回最终的URL
- status:返回响应状态码,请求完成前或请求发生错误,返回0
- statusText:返回响应状态,与status不同的是,它包括响应状态的整个文本(例如,“200 OK”)
- timeout:设置超时时间,以毫秒为单位。默认0,不超时
- ontimeout:继承自XMLHttpRequestEventTarget,请求超时时调用
- upload:返回XMLHttpRequestUpload对象。可以绑定事件追踪上传进度
- XMLHttpRequest事件 事件|事件类型 --|-- onloadstart |获取开始 onprogress |数据传输进行中 onabort |获取操作终止 onerror |获取失败 onload |获取成功 ontimeout |超时 onloadend |获取完成(成功或失败)
- withCredentials:用来指定跨域的请求是否应该使用证书(如cookie或授权header头)
- channel:对象在执行请求时使用的通道
- mozAnon:请求将在没有cookie和身份验证header头的情况下发送
- mozSystem:请求时不会强制执行同源策略
- mozBackgroundRequest:指示对象是否是后台服务器端的请求
方法
- open:初始化一个请求
- abort():终止请求,readyState属性将被置为0
- getAllResponseHeaders():获取响应头,返回以\r\n分隔的字符串
- getResponseHeader():获取指定的响应头 参数|描述 --|-- method |要使用的HTTP方法,比如「GET」、「POST」、「PUT」、「DELETE」、等。对于非HTTP(S) URL被忽略 url |一个DOMString表示要向其发送请求的URL async可选 |一个可选的布尔参数,默认为true,表示要不要异步执行操作。如果值为false,send()方法直到收到答复前不会返回。如果true,已完成事务的通知可供事件监听器使用。如果multipart属性为true则这个必须为true,否则将引发异常 user可选 |可选 可选的用户名用于认证用途;默认为null password可选 |可选 可选的密码用于认证用途,默认为null
- overrideMimeType:重写由服务器返回的MIME type
- send:发送请求。如果请求是异步的(默认),那么该方法将在请求发送后立即返回
- setRequestHeader:设置HTTP请求头的值。您必须在open()之后、send()之前调用setRequestHeader()这个方法
- sendAsBinary:send()方法的变体,用来发送二进制数据
3. 详解Fetch
Fetch被称为下一代Ajax技术,它采用Promise(Promise是es6的主要内容之一)方式来处理数据。它不是基于XMLHttpRequest构建的高阶语法糖,它比XMLHttpRequest更加简单易用,Fetch是一种简洁明了的API,这种简洁的语法提供了更好的一致性。
Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。使之今后可以被使用到更多地应用场景中:无论是 service worker、Cache API、又或者是其他处理请求和响应的方式,甚至是任何一种需要你自己在程序中生成响应的方式。
- Fetch示例
// 发送get请求
fetch('/server',{method:'GET'})
// 将返回的数据转换为json对象
.then(response => response.json())
// 数据处理逻辑
.then(res => console.log(res))
// 异常信息捕获
.catch(err => console.error(err))
- 或者使用async/await语法
async function (){
try{
const response = await fetch('/server',{method:'GET'})
const res = await response.json()
console.log(res)
}catch(err){
console.error(err)
}
}
Fetch更清晰、简洁,使之今后可以被使用到更多地应用场景中:无论是 service worker、Cache API、又或者是其他处理请求和响应的方式,甚至是任何一种需要你自己在程序中生成响应的方式。 Fetch API
Headers
属性
- Headers.append():给现有的header添加一个值, 或者添加一个未存在的header并赋值
- Headers.delete():从Headers对象中删除指定header
- Headers.entries():以迭代器的形式返回Headers对象中所有的键值对
- Headers.get():以ByteString的形式从Headers对象中返回指定header的全部值
- Headers.has():以布尔值的形式从Headers对象中返回是否存在指定的header
- Headers.keys():以迭代器的形式返回Headers对象中所有存在的header名
- Headers.set():替换现有的header的值, 或者添加一个未存在的header并赋值
- Headers.values():以迭代器的形式返回Headers对象中所有存在的header的值
Request
属性
- Request.method(只读):包含请求的方法 (GET, POST, 等)
- Request.url(只读):包含这个请求的URL
- Request.headers(只读):包含请求相关的Headers对象
- Request.context (en-US)(只读): 包含请求的上下文(例如:audio, image, iframe, 等)
- Request.referrer (en-US)(只读):?包含请求的来源 (例如:client)
- Request.referrerPolicy (en-US)(只读):?包含请求来源的策略 (例如:no-referrer)
- Request.mode(只读):包含请求的模式 (例如: cors, no-cors, same-origin, navigate)
- Request.credentials(只读):包含请求的证书(例如: omit, same-origin)
- Request.redirect (en-US)(只读):包含?如何处理重定向模式,它可能是一个 follow ,error或者manual
- Request.integrity (en-US)(只读):包含请求的子资源的完整性值 (例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)
- Request.cache(只读):包含请求的缓存模式 (例如: default, reload, no-cache) Request实现了Body, 所以它还具有以下属性可用:
- Body.body (en-US)(只读):一个简单getter用于曝光一个ReadableStream的主体内容
- Body.bodyUsed (en-US)(只读):存储一个Boolean (en-US)判断主体是否已经被用于一个响应中 方法
- Request.clone():创建当前request的副本 Request Body 接口:
- Body.arrayBuffer() (en-US):返回解决一个ArrayBuffer表示的请求主体的promise
- Body.blob() (en-US):返回解决一个Blob表示的请求主体的promise
- Body.formData() (en-US):返回解决一个FormData表示的请求主体的promise
- Body.json() (en-US):返回解决一个JSON表示的请求主体的promise
- Body.text() (en-US):返回解决一个USVString(文本)表示的请求主体的promise 注意:这些Body功能只能运行一次; 随后的调用将通过空strings/ ArrayBuffers解析
Response
属性
- Response.headers(只读):包含此 Response 所关联的 Headers 对象
- Response.ok(只读):包含了一个布尔值,标示该 Response 成功(HTTP 状态码的范围在 200-299)
- Response.redirected(只读):表示该 Response 是否来自一个重定向,如果是的话,它的 URL 列表将会有多个条目
- Response.status(只读):包含 Response 的状态码 (例如 200 表示成功)
- Response.statusText(只读):包含了与该 Response 状态码一致的状态信息(例如,OK对应 200)
- Response.type(只读):包含 Response 的类型(例如,basic、cors)
- Response.url(只读):包含 Response 的URL
- Response.useFinalURL:包含了一个布尔值,来标示这是否是该 Response 的最终 URL Response Body 接口:
- Body.body (en-US)(只读):一个简单的 getter,用于暴露一个 ReadableStream 类型的 body 内容
- Body.bodyUsed (en-US)(只读):包含了一个布尔值 (en-US)来标示该 Response 是否读取过 Body 方法
- Response.clone():创建一个 Response 对象的克隆
- Response.error():返回一个绑定了网络错误的新的 Response 对象
- Response.redirect():用另一个 URL 创建一个新的 Response Response Body 接口:
- Body.arrayBuffer() (en-US):读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 ArrayBuffer 格式的 Promise 对象。
- Body.blob() (en-US):读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 Blob 格式的 Promise 对象。
- Body.formData() (en-US):读取Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 FormData 格式的 Promise 对象。
- Body.json() (en-US):读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 JSON 格式的 Promise 对象。
- Body.text() (en-US):读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 USVString 格式的 Promise 对象。
4. Ajax和Fetch对比
| Ajax | Fetch |
|---|---|
| 是对XMLHttpRequest对象封装的方法 | 全局量window的一个方法 |
| 能具体区分请求状态 | 只对网络请求报错,对400,500都当做成功的请求,需要封装去处理 |
| 可以监测请求进度 | 无法监测 |
| 原生使用繁琐,大多封装使用 | 语法简洁,简单易懂 |
| 所有浏览器均支持 | 大多数浏览器支持(如:IE不支持) |
5. 结论
- 多数开发人员选择使用Fetch,由于它简洁的语法,语义化的API,使得Fetch比XMLHttpRequest更有优势。目前来看只有两种特定情况下还需要使用XMLHttpRequest支持:
- 非常老的浏览器,如IE。但这个问题随着时间的推移会逐渐改善。
- 上传文件时,如需上传的进度回馈,显示上传进度条。Fetch后续将会支持。
6. 参考资料
- MDN Ajax
- MDN Fetch
- MDN XMLHttpRequest