JS Ajax 封装

2023-09-20 10:27:08

一、 什么是Ajax?

Ajax(Asynchronous JavaScript And XML)是2005年新出现的技术,它的出现是为了解决这样一个场景:整个页面中,只有一小部分的数据需要进行更新,按照传统的前后端交互,我们需要向服务器请求该网页的所有数据,然后再在客户端重新渲染,这无疑是非常低效的操作。因此,Ajax就可以做到只向服务器请求我们想要的那一小部分数据,而不用请求全部数据,进而在刷新整个页面的前提下更新那部分的数据。

举个例子,我们去饭店吃饭,然后点了一桌子菜,后来发现其中有一道菜太咸了,因此我们只需要让服务员端回去给厨师重新做这一道菜再拿回来就行了。

吃饭事件数据更新
我们客户端
菜品页面所有的数据
服务员ajax对象
厨师服务器

当我们发现有一道菜太咸了,不需要让厨师把所有的菜重新做一遍,只要让服务员拿这一道菜回去给厨师重做这一操作就相当于让ajax对象向后端请求那一小部分数据再拿回来更新页面而无需刷新整个页面。

二、 Ajax的优缺点?

当我们发现有一道菜太咸了,不需要让厨师把所有的菜重新做一遍,只要让服务员拿这一道菜回去给厨师重做这一操作就相当于让ajax对象向后端请求那一小部分数据再拿回来更新页面而无需刷新整个页面。

2.1 优点

  • 浏览器默认支持(一般浏览器都是支持JavaScript的)
  • 提高用户体验(不需要刷新整个页面,而只需要局部刷新)
  • 提高页面的性能(只需要请求部分数据,所以数据量就明显下降了)

2.2 缺点

  • 破坏了浏览器的前进和后退功能(Ajax不会改变网页URL,因此不会在浏览器记录前后页面)
  • 对搜索引擎的支持较弱(搜索引擎无法监测到JS引起的数据变化)

三、 Ajax的使用

Ajax的基本流程:创建XHR对象 => 发送数据 => 接收数据

3.1 状态码

既然Ajax涉及到前后端的数据交互,那么我们就先来简单的看一下几种类型的状态码,如下表:

状态码含义
100 ~ 199连接含义
200 ~ 299各种成功的请求
300 ~ 399重定向
400 ~ 499客户端错误
500 ~ 599服务端错误

3.2 xhr的基本使用

在使用xhr之前,我们要创建一个xhr的实例对象:

let xhr = new XMLHttpRequest()

然后再调用xhr对象上的 open() 方法,表示创建一个请求。
open() 方法接收三个参数:

  • 第一个参数: 请求的类型(例如get 、post)
  • 第二个参数: 请求的URL
  • 第三个参数: 是否异步发送请求(默认为true)
// 创建了一个Ajax请求
xhr.open('get', 'example.php', 'true')

光调用了 open() 方法还不够,它只是创建了一个请求,但还没有发送请求,因此我们还要调用xhr对象上的另一个方法,即 send() 方法,表示将请求发送给目标URL

send() 方法接收一个参数:

  • 第一个参数: 作为请求主体发送的数据(例如post请求携带的数据)
// 我们上面创建的是get请求,因此send()方法无需传参
xhr.send()

请求发送出去后,客户端需要接收服务器响应回来的数据,xhr对象中有一些属性,它们存储着服务端返回来的一些数据信息,如下表所示:

属性名含义
response Text服务端返回的文本信息
responseXML服务端返回的XML DOM 文档
statusHTTP 状态码
status TextHTTP状态码说明
readyStatexhr对象的请求响应阶段

既然我们要获取服务端返回的数据,我们就要知道服务端是何时返回数据的,这就可以通过上面表格中的 readyState 属性来判断了
readyState 属性一共有5个值,分别表示不同的请求响应阶段:

  • 0: 还未创建请求,即未调用 open() 方法
  • 1: 已调用 open() 方法,但未发送 send() 方法
  • 2: 已调用send() 方法,但未接收到响应
  • 3: 已接收到部分响应
  • 4: 已接收到全部的响应

同时,xhr对象可以绑定一个 readystatechange 事件,每当 readyState 属性发生改变,都会触发该事件,因此,该事件在一次请求中会被多次触发

xhr.onreadystatechange = function() {
	console.log('readyState属性发生改变了')
}

所以,我们可以在 readystatechange 事件中判断一下 readyState 属性是否为 4,即是否已经接收所有的响应,然后还可以再继续判断一下 status 属性,看看状态码是否为 200,当上述都成立了,我们再去 responseText 属性 或 responseXML 属性中获取响应数据

xhr.onreadystatechange = function() {
	// 判断是否已接收所有响应
	if(xhr.readyState === 4) {
		// 判断状态码是否为200
		if(xhr.status === 200) {
			console.log(xhr.responseText)
		}
	}
}

3.3 ajax原生封装:

//封装一个ajax请求
function ajax(options) {
  //创建XMLHttpRequest对象
  const xhr = new XMLHttpRequest()

  //初始化参数的内容
  options = options || {}
  options.type = (options.type || 'GET').toUpperCase()
  options.dataType = options.dataType || 'json'
  // 处理参数
  let str = ''
  let params = options.data;
  for (let key in params) {
    str += key + '=' + params[key] + '&'
  }
  params = str.slice(0, str.length - 1)


  //发送请求
  if (options.type === 'GET') {
    xhr.open('GET', options.url + '?' + params, true)
    xhr.send(null)
  } else if (options.type === 'POST') {
    xhr.open('POST', options.url, true)
    // post 请求需要设置请求头 模仿表单请求
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    xhr.send(params)
  }
  //接收请求
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      let status = xhr.status
      if (status >= 200 && status < 300) {
        options.success && options.success(xhr.responseText, xhr.responseXML)
      } else {
        options.fail && options.fail(status)
      }
    }
  }
}

3.3.1 触发GET请求:

上面也讲解了Ajax请求的简单应用,同时也是拿 get 请求来举得例子,因此这里我就不多做说明,唯一要讲的就是,get请求所携带的数据是明文的,大小只有4k左右,而且它是写在URL的 ? 后面的,例如这样 example.php?query=4&em=0,所以若是我们要在发送get请求时携带数据,只需要在调用 open() 方法时,将数据写在第二个参数的URL的 ? 后面即可

let btn = document.querySelector('.btn')
btn.addEventListener('click', function () {
  ajax({
    type: 'get',
    dataType: 'json',
    data: { uid: '64dcd451a2d7172b77c03768', aid: "64db6361c57b44a4c47712af" },
    url: 'http://localhost:3456/wyc/getUser',
    success: function (text, xml) {//请求成功后的回调函数
      console.log(JSON.parse(text))
    },
    fail: function (status) {请求失败后的回调函数
      console.log(status)
    }
  })
})

接收结果:
在这里插入图片描述
在这里插入图片描述

3.3.2 调用POST请求:

发送post请求的过程几乎和get请求一样,唯一不一样的是数据的传递。大家都知道post请求的数据是放在请求体中的,因此我们需要调用xhr对象上的 setRequestHeader() 方法来模仿表单提交时的内容类型
该方法传入的参数比较固定,代码如下

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

然后我们上面也说过,send() 方法接收的一个参数是请求主体发送的数据,所以我们的post请求要发送的数据就要作为该方法的参数,代码如下:

xhr.send('query=4&em=0')

完整post请求:

let btn = document.querySelector('.btn')
btn.addEventListener('click', function () {
  ajax({
    type: 'post',
    dataType: 'json',
    data: { uid: '64dcd451a2d7172b77c03768', aid: "64db6361c57b44a4c47712af" },
    url: 'http://localhost:3456/wyc/attention',
    success: function (text, xml) {//请求成功后的回调函数
      console.log(JSON.parse(text))
    },
    fail: function (status) {请求失败后的回调函数
      console.log(status)
    }
  })
})

请求结果:
在这里插入图片描述
在这里插入图片描述

四、Ajax的约束

了解过同源策略以后,我们来看看如何让Ajax不受同源策略的限制而成功发送请求。CORS(跨域资源共享)要求我们在发送请求时自定义一个HTTP头部与服务器进行沟通,我们只需要设置一个名为 Origin 的头部,值为当前页面的源信息(协议、域名、端口),例如 Origin : http://example.com ;然后服务器需要设置一个名为 Access-Control-Allow-Origin 的响应头部,其值为允许跨域访问的源信息,若服务器设置的 Access-Control-Allow-Origin 与我们设置的 Origin 相同,则表示服务器允许我们跨域请求其资源,或者服务器可以将 Access-Control-Allow-Origin 值设为 *,此时表示允许任何域向其发送请求并且不受同源策略的限制。

更多推荐

Python爬虫基础(三):使用Selenium动态加载网页

文章目录系列文章索引一、Selenium简介1、什么是selenium?2、为什么使用selenium3、安装selenium(1)谷歌浏览器驱动下载安装(2)安装selenium二、Selenium使用1、简单使用2、元素定位3、获取元素信息4、交互三、Phantomjs使用(停更)1、什么是Phantomjs2、下

BD就业复习第一天

hive1.分区分桶在Hive中,分区(Partition)和分桶(Bucketing)都是用于数据管理和查询性能优化的技术。它们有不同的用途和特点。分区(Partition):定义:分区是将数据按照某一列或多列的值划分为不同的子目录,使数据可以按照分区列的值进行组织。例如,可以根据日期将数据分为不同的分区,每个分区对

Node18.x基础使用总结(一)

Node18.x基础使用总结1、Node安装2、Buffer2.1、概念2.2、特点2.3、使用2.3.1、创建Buffer2.3.2、Buffer与字符串的转化2.3.3、Buffer的读写3、fs模块3.1、文件写入3.1.1、writeFile异步写入3.1.2、writeFileSync同步写入3.1.3、ap

相对论的应用:GPS导航

“但是数学享有盛誉还有另一个原因:正是数学为精确的自然科学提供了一定程度的安全保障,而没有数学,它们就无法实现这一点。”“就现实而言,数学定律是不确定的;就其确定而言,它们并不涉及现实。”—阿尔伯特·爱因斯坦爱因斯坦的相对论彻底改变了我们对宇宙的理解,从根本上改变了我们感知时间和空间的方式。该理论目前是当代物理学的孪生

基于Android+OpenCV+CNN+Keras的智能手语数字实时翻译——深度学习算法应用(含Python、ipynb工程源码)+数据集(二)

目录前言总体设计系统整体结构图系统流程图运行环境模块实现1.数据预处理2.数据增强3.模型构建1)定义模型结构2)优化损失函数相关其它博客工程源代码下载其它资料下载前言本项目依赖于Keras深度学习模型,旨在对手语进行分类和实时识别。为了实现这一目标,项目结合了OpenCV库的相关算法,用于捕捉手部的位置,从而能够对视

全国职业技能大赛云计算--高职组赛题卷①(私有云)

全国职业技能大赛云计算--高职组赛题卷①(私有云)第一场次题目:OpenStack平台部署与运维任务1基础运维任务(5分)任务2OpenStack搭建任务(15分)任务3OpenStack云平台运维(15分)任务4OpenStack云平台运维开发(15分,本任务只公布考试范围,不公布赛题)需要环境私信博主!!!第一场次

基于罪名法务智能知识图谱(含码源):基于280万罪名预测、20W法务问答与法律资讯问答功能

项目设计集合(人工智能方向):助力新人快速实战掌握技能、自主完成项目设计升级,提升自身的硬实力(不仅限NLP、知识图谱、计算机视觉等领域):汇总有意义的项目设计集合,助力新人快速实战掌握技能,助力用户更好利用CSDN平台,自主完成项目设计升级,提升自身的硬实力。专栏订阅:项目大全提升自身的硬实力[专栏详细介绍:项目设计

Linux内核源码分析 (B.3) 深入理解 Linux 物理内存分配全链路实现

Linux内核源码分析(B.3)深入理解Linux物理内存分配全链路实现文章目录Linux内核源码分析(B.3)深入理解Linux物理内存分配全链路实现@[toc]前文回顾1\.内核物理内存分配接口2.规范物理内存分配行为的掩码gfp\_mask3\.物理内存分配内核源码实现3.1内存分配行为标识掩码ALLOC\_\*

利用LSTM和TensorFlow模拟任意艺术家风格生成新歌词:完整Python实现指南

1.介绍随着深度学习技术的快速进步,我们现在可以使用各种神经网络结构来生成文本、图像甚至音乐。其中,长短期记忆网络(LSTM)是处理序列数据,如文本和时间序列数据的首选技术。在这篇文章中,我们将探讨如何使用LSTM和TensorFlow库来模拟任意艺术家的风格生成新歌词。2.LSTM网络简介长短期记忆网络(LSTM)是

LuatOS-SOC接口文档(air780E)--eink - 墨水屏操作库

常量常量类型解释eink.MODEL_1in02dnumber1.02寸deink.MODEL_1in54number1.54寸eink.MODEL_1in54_V2number1.54寸_V2eink.MODEL_1in54bnumber1.54寸beink.MODEL_1in54b_V2number1.54寸b_V

Node.js 20 —— 几个令人大开眼界的特性

前言:欢迎来到Node.js20Node.js20已经发布,带来了创新和激动人心的新时代。这个开创性的版本于2023年4月18日首次亮相,并将在2023年10月发布长期支持(LTS)版本,并且将持续支持至2026年4月,下面小编就为大家介绍一下Node.js20的几个新特性:1.Node.js权限访问Node.js20

热文推荐