AJAX发送网络请求-封装AJAX-Fetch发送网络请求

秒速五厘米 2023-09-28 13:49 109阅读 0赞

文章目录

    • 1.AJAX网络请求
      • 1.1 AJAX发送请求
      • 1.2 XHR的状态
      • 1.3 XHR其他事件监听
      • 1.4 响应数据和响应类型
      • 1.5 HTTP的响应状态
      • 1.7 GET/POST传递参数
    • 2.AJAX网络请求封装
      • 补充: 过期时间和取消请求
        • 过期时间
        • 取消请求
    • 3.Fetch发生网络请求
      • 3.1 Fetch基本使用
      • 3.2 Fetch数据的响应
      • 3.3 Fetch网络请求的演练
      • 3.4 Fetch POST请求

1.AJAX网络请求

1.1 AJAX发送请求

AJAX 是异步的 JavaScript 和 XML(Asynchronous JavaScript And XML)

  • 它可以使用 JSON,XML,HTML 和 text 文本等格式发送和接收数据;

如何来完成AJAX请求呢?

  • 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
  • 第二步:监听XMLHttpRequest对象状态的变化,或者监听onload事件(请求完成时触发);
  • 第三步:配置网络请求(通过open方法), open方法可以传入两个参数;

    参数一: method(请求的方式: get, post …)

    参数二: url(请求的地址)

  • 第四步:发送send网络请求;

【演示代码】

  1. // 1.创建网络请求对象
  2. const xhr = new XMLHttpRequest()
  3. // 2.监听对象状态的变化
  4. xhr.addEventListener("readystatechange", function() {
  5. // 拿到网络请求的结果
  6. console.log(xhr.response)
  7. })
  8. // 3.配置网络请求
  9. // 参数一: 请求的方式; 参数二: 要请求的url地址
  10. xhr.open("get", "http://192.168.0.110:1888")
  11. // 4.发生网络请求
  12. xhr.send()

发送同步请求:

  • 我们发送网络请求, 默认是异步的, 但是我们也可以发送同步的网络请求
  • 我们是需要将open的第三个参数设置为false (默认时true), 就可以开启同步的请求
  • 当然我们实际开发还是用异步的请求

    // 开启同步
    xhr.open(“get”, “http://192.168.0.110:1888“, false)

1.2 XHR的状态

事实上,我们在一次网络请求中看到状态发生了很多次变化,这是因为对于一次请求来说包括如下的状态:




































状态 描述
0 UNSENT 代理被创建,但尚未调用 open() 方法。
1 OPENED open() 方法已经被调用。
2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
3 LOADING 下载中;responseText 属性已经包含部分数据。
4 DONE 下载操作已完成。

状态0我们是监听不到的


例如: 我们想要获取结果, 应该在下载操作已完成后获取

  1. // 1.创建网络请求对象
  2. const xhr = new XMLHttpRequest()
  3. // 2.监听对象状态的变化
  4. xhr.addEventListener("readystatechange", function() {
  5. // 状态不为4的话直接return
  6. if (xhr.readyState !== XMLHttpRequest.DONE) return
  7. // 拿到的结果是一个字符串, 我们可以转成js对象
  8. const resJSON = JSON.parse(xhr.response)
  9. console.log(resJSON)
  10. })
  11. // 3.配置网络请求
  12. // 参数一: 请求的方式; 参数二: 要请求的url地址
  13. xhr.open("get", "http://192.168.0.110:1888")
  14. // 4.发生网络请求
  15. xhr.send()

注意<:这个状态并非是HTTP的响应状态,而是记录的XMLHttpRequest对象的状态变化。

  • http响应状态通过status获取;

1.3 XHR其他事件监听

我们除了可以监听readystatechange之外, 还有其他的事件可以监听

  • loadstart:请求开始。
  • progress: 一个响应数据包到达,此时整个 response body 都在 response 中。
  • abort:调用 xhr.abort() 取消了请求。
  • error:发生连接错误,例如,域错误。不会发生诸如 404 这类的 HTTP 错误。
  • load:请求成功完成。
  • timeout:由于请求超时而取消了该请求(仅发生在设置了 timeout 的情况下)。
  • loadend:在 load,error,timeout 或 abort 之后触发。

我们也可以在load中获取请求数据:

  1. // 在load中获取请求结果
  2. xhr.addEventListener("load", function() {
  3. console.log(xhr.response)
  4. })

1.4 响应数据和响应类型

发送了请求后,我们需要获取对应的结果:response属性

  • XMLHttpRequest response 属性返回响应的正文内容
  • 返回的类型取决于responseType的属性设置

通过responseType可以设置获取数据的类型

  • 如果将 responseType 的值设置为空字符串,则会使用 text 作为默认值。
  • 设置数据类型, 一般在监听事件之后, 且在send方法之前

    const xhr = new XMLHttpRequest()

    xhr.addEventListener(“load”, function() {

    console.log(xhr.response)
    })

    // 由于responseType默认值为test, 因此我们拿到的结果是一个字符串
    // 告知xhr获取的数据为json类型
    xhr.responseType = “json”

    // json类型接口
    xhr.open(“get”, “http://123.207.32.32:8000/home/multidata“)

    xhr.send()

和responseText、responseXML的区别

  • 早期通常服务器返回的数据是普通的文本和XML,所以我们通常会通过responseText、 responseXML来获取响应结果 , 之后将它们转化成JavaScript对象形式;
  • 目前服务器基本返回的都是json数据,直接设置为json即可

1.5 HTTP的响应状态

前面我们提到, XMLHttpRequest的state是用于记录xhr对象本身的状态变化,并非针对于HTTP的网络请求状态。

如果我们希望获取HTTP响应的网络状态,可以通过status和statusText来获取

  • status是获取状态码
  • statusText是获取状态描述

    const xhr = new XMLHttpRequest()

    xhr.addEventListener(“load”, function() {

    console.log(xhr.response)
    // 1.获取状态码
    console.log(xhr.status) // 200
    // 2.获取状态描述
    console.log(xhr.statusText) // OK
    })

    xhr.responseType = “json”

    xhr.open(“get”, “http://123.207.32.32:8000/home/multidata“)

    xhr.send()

我们写一个不存在的接口, 测试一下状态码和状态描述

  1. const xhr = new XMLHttpRequest()
  2. xhr.addEventListener("load", function() {
  3. console.log(xhr.response) // null
  4. // 1.获取状态码
  5. console.log(xhr.status) // 404
  6. // 2.获取状态描述
  7. console.log(xhr.statusText) // Not Found
  8. })
  9. xhr.responseType = "json"
  10. xhr.open("get", "http://123.207.32.32:8000/aaa/bbb/ccc")
  11. xhr.send()

大家可以再看看刚刚的常用状态码表格
























































常见HTTP状态码 状态描述 信息说明
200 OK 客户端请求成功
201 Created POST请求,创建新的资源
301 Moved Permanently 请求资源的URL已经修改,响应中会给出新的URL
400 Bad Request 客户端的错误,服务器无法或者不进行处理
401 Unauthorized 未授权的错误,必须携带请求的身份信息
403 Forbidden 客户端没有权限访问,被拒接
404 Not Found 服务器找不到请求的资源。
500 Internal Server Error 服务器遇到了不知道如何处理的情况。
503 Service Unavailable 服务器不可用,可能处理维护或者重载状态,暂时无法访问

1.7 GET/POST传递参数

在开发中,我们使用最多的是GET和POST请求,在发送请求的过程中,我们也可以传递给服务器数据。

常见的传递给服务器数据的方式有如下几种 :

  • 方式一:GET请求的query参数(常用)

    1. const xhr = new XMLHttpRequest()
    2. xhr.addEventListener("load", function() {
    3. // 传入的参数服务器会返回
    4. console.log(xhr.response)
    5. })
    6. xhr.responseType = "json"
    7. // 在传入的url输入查询字符串传递参数
    8. xhr.open(
    9. "get",
    10. "http://123.207.32.32:1888/02_param/get?name=kaisa&age=18&address=成都市"
    11. )
    12. xhr.send()

    请求结果

在这里插入图片描述

  • 方式二:POST请求 x-www-form-urlencoded 格式

    1. const xhr = new XMLHttpRequest()
    2. xhr.addEventListener("load", function() {
    3. console.log(xhr.response)
    4. })
    5. xhr.responseType = "json"
    6. // 1.发送post请求
    7. xhr.open("post", "http://123.207.32.32:1888/02_param/posturl")
    8. // 2.告知服务器要发送数据的格式
    9. xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
    10. // 3.在请求体中传入参数
    11. xhr.send("name=kaisa&age=18&address=成都市")

    请求结果

在这里插入图片描述

  • 方式三:POST请求 FormData 格式
  • 方式四:POST请求 JSON 格式(常用)

    1. const xhr = new XMLHttpRequest()
    2. xhr.addEventListener("load", function() {
    3. console.log(xhr.response)
    4. })
    5. xhr.responseType = "json"
    6. // 1.发送post请求
    7. xhr.open("post", "http://123.207.32.32:1888/02_param/posturl")
    8. // 2.告知服务器要发送数据的格式
    9. xhr.setRequestHeader("Content-type", "application/json")
    10. // 3.发送JSON格式的字符串
    11. xhr.send(JSON.stringify({
    12. name: "kaisa", age: 18, height: 1.88 }))

    请求结果

在这里插入图片描述

2.AJAX网络请求封装

在实际开发中, 我们并不会自己封装AJAX, 而是直接使用axios库, 再对axios库进行二次封装

我们封装AJAX原因是借此练习一下前面所学的知识

由于我们每次使用网络请求, 都写写很多行同样的代码, 使用起来是非常不方便的, 我们封装的目的就是为了使用起来更方便

封装步骤的解释写在代码注释里面, 源代码和测试代码给大家

  1. // 定义一个函数封装ajax,
  2. // 由于使用参数可能会传很多个, 因此我们可以让使用者传入一个对象
  3. function myajax({
  4. url,
  5. method = "get",
  6. date = {
  7. },
  8. success,
  9. failure
  10. } = {
  11. }) {
  12. // 1.创建对象
  13. const xhr = new XMLHttpRequest()
  14. // 2.监听数据
  15. xhr.onload = function() {
  16. // 用响应码判断是否成功
  17. if (xhr.status >= 200 && xhr.status < 300) {
  18. success && success(xhr.response)
  19. } else {
  20. failure && failure({
  21. status: xhr.status, message: xhr.statusText })
  22. }
  23. }
  24. // 3.设置响应类型
  25. xhr.responseType = "json"
  26. // 考虑get请求放在date对象中的情况单独处理
  27. if (method.toUpperCase() === "GET") {
  28. const urlStrings = []
  29. for (key in date) {
  30. urlStrings.push(`${
  31. key}=${
  32. date[key]}`)
  33. }
  34. url = url + "?" + urlStrings.join("&")
  35. xhr.open(method, url)
  36. xhr.send()
  37. } else {
  38. // 4.open方法
  39. xhr.open(method, url)
  40. // 5.send方法
  41. xhr.setRequestHeader("Content-type", "application/json")
  42. xhr.send(JSON.stringify(date))
  43. }
  44. }
  45. // 测试get请求
  46. myajax({
  47. url: "http://123.207.32.32:1888/02_param/get",
  48. date: {
  49. name: "get",
  50. age: 18
  51. },
  52. // 传入一个请求成功的回调
  53. success: function(res) {
  54. console.log(res)
  55. },
  56. // 传入失败的回调
  57. failure: function(err) {
  58. console.log("err", err)
  59. }
  60. })
  61. // 测试post请求
  62. myajax({
  63. url: "http://123.207.32.32:1888/02_param/posturl",
  64. method: "post",
  65. // 传入一个请求成功的回调
  66. success: function(res) {
  67. console.log(res)
  68. },
  69. date: {
  70. name: "post",
  71. age: 18
  72. },
  73. // 传入失败的回调
  74. failure: function(err) {
  75. console.log("err", err)
  76. }
  77. })

我们对上面的基本封装做一点优化, 为了防止回调地狱的情况出现, 我们可以返回一个promise, 并且不需要再传入成功的回调和失败的回调, 因为promise中有

  1. function myajax({
  2. url,
  3. method = "get",
  4. date = {
  5. }
  6. } = {
  7. }) {
  8. // 返回一个promise
  9. return new Promise((resolve, reject) => {
  10. const xhr = new XMLHttpRequest()
  11. xhr.onload = function() {
  12. if (xhr.status >= 200 && xhr.status < 300) {
  13. // 使用resolve成功的回调
  14. resolve(xhr.response)
  15. } else {
  16. // 使用reject失败的回调
  17. reject({
  18. status: xhr.status, message: xhr.statusText })
  19. }
  20. }
  21. xhr.responseType = "json"
  22. if (method.toUpperCase() === "GET") {
  23. const urlStrings = []
  24. for (key in date) {
  25. urlStrings.push(`${
  26. key}=${
  27. date[key]}`)
  28. }
  29. url = url + "?" + urlStrings.join("&")
  30. xhr.open(method, url)
  31. xhr.send()
  32. } else {
  33. xhr.open(method, url)
  34. xhr.setRequestHeader("Content-type", "application/json")
  35. xhr.send(JSON.stringify(date))
  36. }
  37. })
  38. }
  39. // 测试get请求
  40. myajax({
  41. url: "http://123.207.32.32:1888/02_param/get",
  42. date: {
  43. name: "get",
  44. age: 18
  45. }
  46. // then中成功的结果
  47. }).then(res => {
  48. console.log(res)
  49. // catch中失败的结果
  50. }).catch(err => {
  51. console.log(err)
  52. })
  53. // 测试post请求
  54. myajax({
  55. url: "http://123.207.32.32:1888/02_param/posturl",
  56. method: "post",
  57. date: {
  58. name: "post",
  59. age: 18
  60. }
  61. // then中成功的结果
  62. }).then(res => {
  63. console.log(res)
  64. // catch中失败的结果
  65. }).catch(err => {
  66. console.log(err)
  67. })

补充: 过期时间和取消请求

下面我用的是一个延时的接口

过期时间

在网络请求的过程中,为了避免过长的时间服务器无法返回数据,通常我们会为请求设置一个超时时间:timeout。

  • 当达到超时时间后依然没有获取到数据,那么这个请求会自动被取消掉;
  • 默认值为0,表示没有设置超时时间;

下面写个案例, 如果超过3000毫秒没有请求到数据就取消本次网络请求

  • 请求超时可以在timeout中监听

    const xhr = new XMLHttpRequest()

    xhr.addEventListener(“load”, function() {

    console.log(xhr.response)
    })

    // 请求超时可以在timeout中监听
    xhr.addEventListener(“timeout”, function() {

    console.log(“请求超时”)
    })

    xhr.responseType = “json”

    xhr.timeout = 3000

    xhr.open(“get”, “http://123.207.32.32:1888/01_basic/timeout“)

    xhr.send()

取消请求

取消网络请求, 我们也可以通过abort方法强制 (手动) 取消请求

  • 请求取消可以在abort中监听

3.Fetch发生网络请求

3.1 Fetch基本使用

Fetch可以看做是早期的XMLHttpRequest的替代方案,它提供了一种更加现代的处理方案:

比如返回值是一个Promise,提供了一种更加优雅的处理结果方式

  • 在请求发送成功时,调用resolve回调then;
  • 在请求发送失败时,调用reject回调catch;

比如不像XMLHttpRequest一样,所有的操作都在一个对象上

fetch函数的使用

fetch(input[, init])

input:定义要获取的资源地址,可以是一个URL字符串,也可以使用一个Request对象(实验性特性)类型;

init:其他初始化参数, 是一个对象

  • method: 请求使用的方法,如 GET、POST;
  • headers: 请求的头信息;
  • body: 请求的 body 信息;

【演示代码】

发送一个get请求(先了解一下 马上会详细分析)

  1. fetch("http://123.207.32.32:8000/home/multidata").then(res => {
  2. // 获取具体的结果还需调用一次
  3. // 如果是文本就res.text, 其他的同样的道理
  4. res.json().then(res => {
  5. console.log(res)
  6. })
  7. }).catch(err => {
  8. console.log(err)
  9. })

3.2 Fetch数据的响应

Fetch的数据响应主要分为两个阶段 :

阶段一:当服务器返回了响应(response)

  • fetch 返回的 promise 就使用内建的 Response class 对象来对响应头进行解析;
  • 在这个阶段,我们可以通过检查响应头,来检查 HTTP 状态以确定请求是否成功;
  • 如果 fetch 无法建立一个 HTTP 请求,例如网络问题,亦或是请求的网址不存在,那么 promise 就会 reject;
  • 异常的 HTTP 状态,例如 404 或 500,不会导致出现 error;

我们可以在 response 的属性中看到 HTTP 状态

  • status:HTTP 状态码,例如 200;
  • ok:布尔值,如果 HTTP 状态码为 200-299,则为 true;

    fetch(“http://123.207.32.32:8000/home/multidata").then(res => {

  1. // response中查看状态码, 状态描述
  2. console.log(res.status) // 200
  3. console.log(res.statusText) // OK
  4. console.log(res.ok) // true
  5. }).catch(err => {
  6. console.log(err)
  7. })

第二阶段,为了获取 response body,我们需要使用一个其他的方法调用, 这个方法同样返回Promise。

  • response.text() —— 读取 response,并以文本形式返回 response;
  • response.json()—— 将 response 解析为 JSON;

    fetch(“http://123.207.32.32:8000/home/multidata").then(res => {

  1. // 第二阶段, 同样返回Promise
  2. res.json().then(res => {
  3. // 拿到最终结果
  4. console.log(res)
  5. })
  6. }).catch(err => {
  7. console.log(err)
  8. })

3.3 Fetch网络请求的演练

基于Promise的使用方案

  1. fetch("http://123.207.32.32:8000/home/multidata").then(res => {
  2. // 获取具体的结果还需调用一次
  3. // 如果是文本就res.text, 其他的同样的道理
  4. return res.json()
  5. }).then(res => {
  6. console.log(res)
  7. }).catch(err => {
  8. console.log(err)
  9. })

基于async、await的使用方案

  1. async function getDate() {
  2. const response1 = await fetch("http://123.207.32.32:8000/home/multidata")
  3. const response2 = await response1.json()
  4. // 打印结果
  5. console.log(response2)
  6. }
  7. getDate()

3.4 Fetch POST请求

创建一个 POST 请求,或者其他方法的请求,我们需要使用 fetch 选项

method:HTTP 方法,例如 POST,

body:request body,其中之一:

  • 字符串(例如 JSON 编码的),
  • FormData 对象,以 multipart/form-data 形式发送数据,

    async function getDate() {

    // post请求需要在fetch方法中传入第二个参数
    const response1 = await fetch(“http://123.207.32.32:1888/02_param/postjson",{

    1. method: "post",
    2. headers: {
    3. "Content-type": "application/json"
    4. },
    5. // 参数防砸body中
    6. body: JSON.stringify({
    7. username: "aaa",
    8. postname: "123456"
    9. })

    })
    const response2 = await response1.json()
    // 打印结果
    console.log(response2)
    }

    getDate()

发表评论

表情:
评论列表 (有 0 条评论,109人围观)

还没有评论,来说两句吧...

相关阅读