1、AJAX
AJAX全称(Async Javascript and XML)。即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页。
Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用JavaScript来操作DOM而更新页面。
实现过程
1)创建 Ajax的核心对象 XMLHttpRequest对象,通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接
2)构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send() 方法发送给服务器端
3)通过 XMLHttpRequest 对象提供的 onreadystatechange事件监听服务器端你的通信状态,接受并处理服务端向客户端响应的数据结果,将处理结果更新到 HTML页面中
XHR详解
1)创建XMLHttpRequest对象:const xhr = new XMLHttpRequest()
通过XMLHttpRequest()构造函数初始化一个XMLHttpRequest实例对象。
2)与服务器建立连接:xhr.open(method, url, [async],[ user],[ password])
通过XMLHttpRequest对象的open()方法与服务器建立连接。open()方法规定请求的类型、URL 以及是否异步处理请求。
method:表示当前的请求方式,常见的是GET、POST。
url:服务器地址。
async:布尔值,表示是否异步执行操作,默认为true。
user:可选的用户名,用于认证用途,默认为null。
password:可选的密码,用于认证用途,默认为null。
3)给服务器发送数据:xhr.send([body])
通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端。
body: 在 XHR 请求中要发送的数据体,如果不传递数据则为 null。
如果使用GET请求发送数据的时候,需要注意如下:
a、将请求数据添加到open()方法中的url地址中。
b、发送请求数据中的send()方法中参数设置为null。
4)绑定onreadystatechange事件
onreadystatechange 事件用于监听服务器端的通信状态,主要监听的属性为XMLHttpRequest.readyState 。readyState有五个状态:
只要 readyState属性值一变化,就会触发一次 readystatechange 事件。
XMLHttpRequest.responseText属性用于接收服务器端的响应结果。
status: 响应状态码值, 比如200, 404。
statusText: 响应状态文本。
onreadystatechange: 绑定readyState改变的监听。
responseType: 指定响应数据类型, 如果是json, 得到响应后自动解析响应体数据。
response: 响应体数据, 类型取决于responseType的指定。
原生示例:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/serve');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status == 200) {
info.innerHTML = xhr.response;
} else {
console.log("请求失败!")
}
}
}
JQuery ajax
JQuery ajax是对原生XHR的封装。还增添了对JSONP的支持。
特点:提高了性能和速度;交互性好;Ajax对Web服务器进行异步调用。底层使用XMLHttpRequest。
缺点:Ajax应用程序中的安全性较低(容易收到CSRF和XSS攻击),因为所有文件都是在客户端下载的。
本身是针对MVC的编程,不符合现在前端MVVM的浪潮。MVVM(Model-View-ViewModel), 源自于经典的 Model–View–Controller(MVC)模式。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层。
1)url:请求地址。要求为String类型的参数。
2)type:请求方式(post或get)默认为get。要求为String类型的参数。
3)async:要求为Boolean类型,默认设置为true,所有请求均为异步请求。如果需要发送同步请求,请将此选项设置为false。
4)cache:要求为Boolean类型的参数,默认为true(当dataType为script时,默认为false),设置为false将不会从浏览器缓存中加载请求信息。
5)data:要求为Object或String类型的参数,发送到服务器的数据。
6)dataType:要求为String类型的参数,预期服务器返回的数据类型。
7)success:要求为Function类型的参数,请求成功后调用的回调函数。
8)error:要求为Function类型的参数,请求失败时被调用的函数。
2、Axios
axios基于promise用于浏览器和node.js的http客户端,是通过promise实现对ajax技术的一种封装。本质上也是对原生XHR的封装,只不过它是Promise的实现版本。
特点:a、在浏览器中创建XMLHttpRequest;
b、支持Promise API;
c、提供了一些并发请求的接口;
e、支持拦截请求和响应;
f、转换请求和响应数据,自动转换JSON数据;
g、客户端支持防御CSRF/XSRF.
1)常用语法
axios.create(config):根据指定配置创建一个新的axios, 也就就每个新axios都有自己的配置。新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的。
应用:项目中有部分接口需要的配置与另一部分接口需要的配置不太一样,创建 2 个新axios,每个都有自己特有的配置, 分别应用到不同要 求的接口请求中。
instance 与 axios 的区别?
相同:
a、都是一个能发任意请求的函数:request(config)
(2) 都有发特定请求的各种方法:get()/post()/put()/delete()
(3) 都有默认配置和拦截器的属性:defaults/interceptors。
不同:
(1) 默认匹配的值很可能不一样
(2)instance没有axios后面添加的一些方法:create()/CancelToken()/all()
2)拦截器函数/ajax 请求/请求的回调函数的调用顺序
调用axios()并不是立即发送ajax请求, 而是需要经历一个较长的流程。
流程:请求拦截器2 => 请求拦截器 1 => 发ajax请求 => 响应拦截器1 => 响应拦截器 2 => 请求的回调。
此流程是通过promise串连起来的,请求拦截器传递的是config, 响应 拦截器传递的是response。
整体流程: request(config) ==> dispatchRequest(config) ==> xhrAdapter(config)request(config): 将 请求拦截器 / dispatchRequest() / 响应拦截器,通过 promise 链串连起来, 返回 promisedispatchRequest(config): 转换请求数据 ===> 调用 xhrAdapter() 发请求 ===> 请求返回后,转换响应数据,返回 promisexhrAdapter(config): 创建 XHR 对象, 根据 config 进行相应设置, 发送特定请求, 并接收响应数据, 返回 promise 。
3)XHR的ajax封装(简单版axios)
主要分为如下的步骤:
代码实现:
3、fetch
fetch()号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。fetch是一个低层次的API,你可以把它考虑成原生的XHR,所以使用起来并不是那么舒服,需要进行封装。
fetch()采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象),更合理一些;相比之下,XMLHttpRequest 的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码。
a、只有网络错误,或者无法连接时,fetch()才会报错,其他情况都不会报错,而是认为请求成功。服务器返回的状态码是 4xx 或 5xx,fetch()也不会报错(即 Promise 不会变为rejected状态)。只有通过Response.status属性,得到 HTTP 回应的真实状态码,才能判断请求是否成功。另一种方法是判断response.ok是否为true。
b、fetch默认不会带cookie,需要添加配置项credentials;
c、fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject和Promise.race结合setTimeout实现的超时控制并不能阻止请求过程继续在后台执行,造成了量的浪费;
d、fetch没有办法原生监测请求的进度,而XHR可以。
fetch()必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个 Promise 对象,resolve 对应请求的Response。你也可以传一个可选的第二个参数init。
1)Response 对象
fetch()请求成功以后,得到的是一个Response 对象。它对应服务器的 HTTP 回应。Response 包含的数据通过 Stream 接口异步读取,但是它还包含一些同步属性,对应 HTTP 回应的标头信息(Headers),可以立即读取。
Response 对象的同步属性:
a、Response.ok属性返回一个布尔值,表示请求是否成功,true对应 HTTP 请求的状态码 200 到 299,false对应其他的状态码。
b、Response.status属性返回一个数字,表示 HTTP 回应的状态码(例如200,表示成功请求)。
c、Response.statusText属性返回一个字符串,表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回"OK")。
d、Response.url属性返回请求的 URL。如果 URL 存在跳转,该属性返回的是最终 URL。
e、Response.type属性返回请求的类型。
f、Response.redirected属性返回一个布尔值,表示请求是否发生过跳转。
2)Response.headers 属性
Response 对象还有一个Response.headers属性,指向一个Headers 对象,对应 HTTP 回应的所有标头。Headers 对象提供了以下方法,用来操作标头。
3)Response读取内容的方法
Response对象根据服务器返回的不同类型的数据,提供了不同的读取方法。
Stream 对象只能读取一次,读取完就没了。这意味着,上面的五个读取方法,只能使用一个,否则会报错。Response 对象提供Response.clone()方法,创建Response对象的副本,实现多次读取。
4)fetch()配置对象的完整 API
fetch()请求的底层用的是Request() 对象的接口,参数完全一样,因此上面的 API 也是Request()的 API。
a、method:http请求的方法,POST、DELETE、PUT等属性。
b、headers:一个对象,用来定制HTTP请求的标头。
c、body:POST请求的数据体。
d、cache属性指定如何处理缓存。
e、mode属性指定请求的模式。
f、credentials属性指定是否发送 Cookie。跨域请求发送 Cookie,需要将credentials属性设为include。
g、keepalive属性用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。
h、redirect属性指定 HTTP 跳转的处理方法。
5)取消fetch()请求
fetch()请求发送以后,如果中途想要取消,需要使用AbortController对象。首先新建 AbortController 实例,然后发送fetch()请求,配置对象的signal属性必须指定接收 AbortController 实例发送的信号controller.signal。
controller.abort()方法用于发出取消信号。这时会触发abort事件,这个事件可以监听,也可以通过controller.signal.aborted属性判断取消信号是否已经发出。