赞
踩
Fetch、Axios、Ajax 都是前端用于发送HTTP请求的工具或技术:
AJAX(Asynchronous JavaScript and XML,异步 JavaScript 和 XML)是一种使用现有的网页技术来创建异步请求和更新页面内容的方法。Ajax 本身不是一种技术,而是一种将一些现有技术结合起来使用的方法,包括:HTML 或 XHTML、CSS、JavaScript、DOM、XML、XSLT、以及最重要的 XMLHttpRequest 对象。
当使用结合了这些技术的 Ajax 模型以后,网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面。这使得程序能够更快地回应用户的操作。Ajax 最吸引人的特性是它的“异步”性质,这意味着它可以与服务器通信、交换数据并更新页面,而无需刷新页面。
Ajax 是一种使用浏览器提供的 XMLHttpRequest 对象实现的技术,用于在不刷新整个页面的情况下进行异步请求和更新页面内容。可以说 Ajax 是基于浏览器提供的 XMLHttpRequest 对象来实现的。
以下是基于原生 JavaScript 的 AJAX 请求代码示例:
- // 创建 XMLHttpRequest 对象
- const xhr = new XMLHttpRequest();
-
- // 指定请求的方法和 URL
- xhr.open('GET', 'api_url', true); // 第三个参数 true 表示异步请求
-
- // 设置请求头(如果需要)
- xhr.setRequestHeader('Content-Type', 'application/json'); // 根据实际需求设置请求头
-
- // 注册一个回调函数来处理响应
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4 && xhr.status === 200) {
- const response = JSON.parse(xhr.responseText); // 处理响应数据
- // 在这里执行相应的操作
- console.log(response);
- }
- };
-
- // 发送请求
- xhr.send();
虽然 AJAX 是一种强大的技术,但相对于 Axios 和 Fetch API,它有以下一些缺点:
Fetch 是一种用于进行网络请求的现代 JavaScript API。它提供了一种简单、灵活且功能强大的方式,用于从服务器获取资源并处理响应。
Fetch API 在浏览器中原生支持,并且以 Promise 为基础,使得异步请求更加直观和易用。使用 Fetch API,可以执行各种类型的请求(如 GET、POST、PUT、DELETE 等),发送请求时可以设置请求头、请求参数,以及处理响应数据。
与传统的 AJAX 相比,Fetch API 具有以下优点:
Fetch API 提供了一个全局的 fetch()
方法,该方法提供了一种简单、逻辑的方式来通过网络异步获取资源。
fetch()
方法的语法使用- fetch(url, options)
- .then(response => {
- // 在这里处理响应
- })
- .catch(error => {
- // 在这里处理错误
- });
这里有两个参数:
url :是发送网络请求的地址。
options:发送请求参数,
- get 方式
-
- 只需要在url中加入传输数据,options中加入请求方式。如下面代码所示:
-
- function login(){
- fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`,{
- method:'GET'
- }).then(response=>{
- console.log('响应',response)
- })
- }
- post 方式
-
- 使用 post 发送请求时,需要设置请求头、请求数据等。
-
- fetch(`http://localhost:80/ES6练习题/53fetch.html`,{
- method:'POST',
- headers:{
- 'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
- },
- body:`user=${user.value}&pas=${pas.value}`
- }).then(response=>{
- console.log('响应',response)
- })
response
一旦获取到响应(Response),返回的对象包含以下属性:
response 对象根据服务器返回的不同类型数据,提供了不同的读取方法。
文本数据:
response.text()
:以文本形式读取响应体的数据。response.json()
:将响应体的数据解析为JSON对象。二进制数据:
response.arrayBuffer()
:以ArrayBuffer形式读取响应体的数据。response.blob()
:以Blob形式读取响应体的数据。表单数据:
response.formData()
:以FormData对象形式读取响应体的数据。流数据:
response.body
:以可读流形式读取响应体的数据。- body 属性返回一个 ReadableStream 对象,供用户操作,可以用来分块读取内容,
- 显示下载的进度就是其中一种应用。
- const response = await fetch('flower.jpg');
- const reader = response.body.getReader();
- //response.body.getReader() 返回一个遍历器,这个遍历器 read() 方法每次
- //都会返回一个对象,表示本次读取的内容块。
- while(true) {
- const {done, value} = await reader.read();
- if (done) {
- break;
- }
- console.log(`Received ${value.length} bytes`)
- }
如果是上传数据:
- 将上个实例,改写成 post 方式提交数据,代码如下:
-
- fetch(`http://localhost:80/ES6练习题/53fetch.html`,{
- method:'POST',
- headers:{
- 'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
- },
- body:`user=${user.value}&pas=${pas.value}`
- }).then(response=>{
- console.log('响应',response)
- })
- //如果是提交json数据时,需要把json转换成字符串。如
-
- body:JSON.stringify(json)
- //如果提交的是表单数据,使用 formData转化下,如:
-
- body:new FormData(form)
- //上传文件,可以包含在整个表单里一起提交,如:
-
- const input = document.querySelector('input[type="file"]');
-
- const data = new FormData();
- data.append('file', input.files[0]);
- data.append('user', 'foo');
-
- fetch('/avatars', {
- method: 'POST',
- body: data
- });
- //上传二进制数据,将 bolb 或 arrayBuffer 数据放到body属性里,如:
-
- let blob = await new Promise(resolve =>
- canvasElem.toBlob(resolve, 'image/png')
- );
-
- let response = await fetch('/article/fetch/post/image', {
- method: 'POST',
- body: blob
- });
response.clone()
stream 对象只能读取一次,读取完就没了,这意味着,上边的五种读取方法,只能使用一个,否则会报错。
因此 response 对象提供了 clone() 方法,创建 respons 对象副本,实现多次读取。
- const response1 = await fetch('flowers.jpg');
- const response2 = response1.clone();
-
- const myBlob1 = await response1.blob();
- const myBlob2 = await response2.blob();
-
- image1.src = URL.createObjectURL(myBlob1);
- image2.src = URL.createObjectURL(myBlob2);
fetch 是相对较新的技术,IE浏览器不支持,还有其他低版本浏览器也不支持,因此如果使用fetch时,需要考虑浏览器兼容问题。
解决办法:引入 polyfill 完美支持 IE8 以上。
polyfill 的原理就是探测fetch是否支持,如果不支持则用 xhr 实现。支持 fetch 的浏览器,响应中文会乱码,所以使用 fetch-detector 和 fetch-ie8 解决乱码问题。
fetch默认不带cookie
传递cookie时,必须在header参数内加上 credentials:'include',才会像 xhr 将当前cookie 带有请求中。
异常处理
fetch 不同于 xhr ,xhr 自带取消、错误等方法,所以服务器返回 4xx 或 5xx 时,是不会抛出错误的,需要手动处理,通过 response 中的 status 字段来判断。
取消请求
在标准的 Fetch API 中,没有提供直接取消 Fetch 请求的内置方法。但是,可以使用以下方法来模拟或实现取消 Fetch 请求的效果。
使用 AbortController 和 AbortSignal:这是一种较新的浏览器特性,用于生成可以取消请求的信号。可以创建一个 AbortController对象,然后将其关联到 Fetch 请求中,当需要取消请求时,调用 AbortController 的 abort()方法:
- // 创建 AbortController 和关联的 signal
- const abortController = new AbortController();
- const signal = abortController.signal;
-
- // 发起 Fetch 请求,并将 signal 传递给 fetch 函数
- fetch(url, { signal })
- .then(response => {
- // 处理响应
- })
- .catch(error => {
- if (error.name === 'AbortError') {
- // 请求已被取消
- } else {
- // 处理其他错误
- }
- });
-
- // 当需要取消请求时,调用 abort() 方法
- abortController.abort();
Axios 是一个基于 Promise 网络请求第三方库,用于在浏览器和 Node.js 中进行 HTTP 请求。在服务端它使用原生 node.js http 模块, 而在客户端,本质上还是对原生XMLHttpRequest的封装,只不过它是基于Promise的,符合最新的ES规范
具备以下特点:
// 使用 npm 安装
npm install axios
// 使用 yarn 安装
yarn add axios
请求方法
axios 支持通过简写方式来执行不同类型的请求:
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
对于这些方法,第一个参数是请求的 URL,config 和 data 分别是请求的配置项和请求参数,这两个参数都是可选的。
-
- 下面来进行一个简单的 get 请求:
- axios.get('https://api.example.com/data')
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理错误
- console.error(error);
- });
-
- //post
- const options = {
- headers: {'X-Custom-Header': 'value'}
- };
-
- axios.post('/save', { a: 10 }, options)
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理错误
- console.error(error);
- });
当作为第二个参数传递给 axios.post
函数时,Axios 会自动将 JavaScript 对象序列化为 JSON。这样就无需将 POST 正文序列化为 JSON。Axios 还会自动将 Content-Type
请求头设置为 application/json
。
axios实例的相关配置
(1)配置列表
请求拦截、响应拦截
Axios 中,可以使用拦截器来拦截请求和响应,并在其被发送或接收之前进行一些额外的处理,可以通过 axios.interceptors
对象来添加拦截器。
- // 添加请求拦截器
- axios.interceptors.request.use(config => {
- // 在发送请求之前做一些处理
- console.log('请求拦截器');
-
- // 修改请求配置
- config.headers['Authorization'] = 'Bearer token';
-
- return config;
- }, error => {
- // 处理请求错误
- console.error('请求出错:', error);
- });
-
- // 添加响应拦截器
- axios.interceptors.response.use(response => {
- // 在接收到响应数据之前做一些处理
- console.log('响应拦截器');
-
- // 修改响应数据
- response.data = { ...response.data, extraField: 'Extra Value' };
-
- return response;
- }, error => {
- // 处理响应错误
- console.error('响应出错:', error);
- });
-
- // 发送请求
- axios.get('https://api.example.com/data')
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理请求或响应错误
- console.error(error);
- });
单个请求响应拦截
可以使用 transformRequest 方法在请求发送之前对请求数据进行转换和处理,它是一个请求拦截器,是一个可选的函数。
transformRequest 函数接收两个参数:requestData 和 requestHeaders。
requestData 是要发送的请求数据,requestHeaders 是要发送的请求头信息。
可以在transformRequest 函数内部对这些参数进行修改,并将修改后的值返回。返回的结果将作为实际发送请求的数据。
- axios({
- url: 'https://api.example.com/data',
- method: 'post',
- data: {
- id: 12345,
- name: 'John Doe'
- },
- transformRequest: (data, headers) => {
- // 对请求数据进行转换和处理
- const modifiedData = { ...data }; // 复制原始数据
-
- // 修改数据或添加额外字段
- modifiedData.extraField = 'Extra Value';
-
- // 修改请求头信息
- headers['Content-Type'] = 'application/json';
-
- return JSON.stringify(modifiedData); // 返回处理后的数据
-
- }
- })
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理错误
- console.error(error);
- });
-
- axios.get('https://api.example.com/data', {
- transformResponse: (data) => {
- // 对响应数据进行转换和处理
- const parsedData = JSON.parse(data); // 解析 JSON 字符串
-
- // 修改数据或添加额外字段
- parsedData.extraField = 'Extra Value';
-
- return parsedData; // 返回处理后的数据
- }
- })
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理错误
- console.error(error);
- });
客户端支持 XSRF 防护
跨站请求伪造(简称 XSRF)是一种攻击 Web 应用的方法,其中攻击者将自己伪装成合法且受信任的用户,以影响应用程序与用户浏览器之间的交互。有很多方法可以执行此类攻击,包括XMLHttpRequest。
幸运的是,Axios 通过允许在发出请求时嵌入额外的身份验证数据来防止 XSRF。这使得服务器能够发现来自未经授权的位置的请求。以下是使用 Axios 完成此操作的方法:
- const options = {
- method: 'post',
- url: '/login',
- xsrfCookieName: 'XSRF-TOKEN',
- xsrfHeaderName: 'X-XSRF-TOKEN',
- };
-
- axios(options)
- .then(response => {
- // 处理成功响应
- console.log(response.data);
- })
- .catch(error => {
- // 处理请求错误
- console.error(error);
- });
这里有两个 xsrf 相关的属性:
请求进度
Axios 的另一个有趣的功能是能够监控请求的进度,这在下载或上传大文件时特别有用,可以使用onUploadProgress 和 onDownloadProgress 两个配置选项来实现。
对于上传进度,可以使用 onUploadProgress 配置选项。它会在上传数据时触发,并提供关于上传进度的信息。
- axios.post('/upload', data, {
- onUploadProgress: progressEvent => {
- const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
- console.log(`上传进度:${percentCompleted}%`);
- },
- })
- .then(response => {
- console.log(response.data);
- })
- .catch(error => {
- console.error(error);
- });
这里发送了一个 POST 请求,在配置选项中使用了 onUploadProgress。当数据上传过程中触发进度事件时,回调函数会被执行。在回调函数中,我们计算出了已上传数据的百分比,并将其打印出来。
对于下载进度,可以使用 onDownloadProgress 配置选项。它会在接收到响应数据时触发,并提供关于下载进度的信息。
- axios.get('/download', {
- onDownloadProgress: progressEvent => {
- const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
- console.log(`下载进度:${percentCompleted}%`);
- },
- })
- .then(response => {
- console.log(response.data);
- })
- .catch(error => {
- console.error(error);
- });
取消请求(不常用)
在 Axios 中,可以使用取消令牌(cancel token)来取消请求。取消令牌是一个对象,它表示一个具体的取消操作,并允许在需要时中止请求。
- let source = axios.CancelToken.source();
- axios
- .get("/data.json", {
- cancelToken: source.token
- })
- .then(res => {
- console.log(res);
- }).catch(err=>{
- if (axios.isCancel(error)) {
- console.log('请求已被取消:', error.message);
- } else {
- console.error(error);
- } })
- // 取消请求(参数msg)
- source.cancel('自定的的字符串可选')
这里,先创建了一个取消令牌源 source。然后,发送 GET 请求时将 cancelToken 配置选项设置为 source.token,即将取消令牌与该请求关联起来。当需要取消请求时,调用source.cancel() 方法,并传入取消请求的原因作为参数。
在请求的 .catch() 方法中,我们使用 axios.isCancel(error) 来判断捕获的错误是否是一个已取消的请求。如果是取消请求导致的错误,则会打印出 ‘请求已被取消’ 的提示信息。否则,将打印出其他类型的错误。
注意,如果不设置 timeout
选项,默认情况下 Axios 请求是没有超时限制的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。