JavaScript XHR、Fetch

1 前端数据请求方式

2 Http协议的解析

3 XHR的基本用法

4 XHR的进阶和封装

5 Fetch的使用详解

6 前端文件上传流程

早期的页面都是后端做好,浏览器直接拿到页面展示的,用到的是jsp、asp、php等等的语言。 这个叫做服务器端渲染SSR。

这里后端向前端发送数据,数据结果前端渲染页面,这个叫做 客户端渲染。

FeHelper插件的演练

1

javascript 复制代码
 const banners = {
      "banner": {
        "context": {
          "currentTime": 1538014774
        },
        "isEnd": true,
        "list": [
          {
            "acm": "3.mce.2_10_1jhwa.43542.0.ccy5br4OlfK0Q.pos_0-m_454801-sd_119",
            "height": 390,
            "height923": 390,
            "image": "https://s10.mogucdn.com/mlcdn/c45406/180926_45fkj8ifdj4l824l42dgf9hd0h495_750x390.jpg",
            "image923": "https://s10.mogucdn.com/mlcdn/c45406/180926_7d5c521e0aa3h38786lkakebkjlh8_750x390.jpg",
            "link": "https://act.mogujie.com/huanxin0001?acm=3.mce.2_10_1jhwa.43542.0.ccy5br4OlfK0Q.pos_0-m_454801-sd_119",
            "title": "焕新女装节",
            "width": 750,
            "width923": 750
          },
          {
            "acm": "3.mce.2_10_1ji16.43542.0.ccy5br4OlfK0R.pos_1-m_454889-sd_119",
            "height": 390,
            "height923": 390,
            "image": "https://s10.mogucdn.com/mlcdn/c45406/180926_31eb9h75jc217k7iej24i2dd0jba3_750x390.jpg",
            "image923": "https://s10.mogucdn.com/mlcdn/c45406/180926_14l41d2ekghbeh771g3ghgll54224_750x390.jpg",
            "link": "https://act.mogujie.com/ruqiu00001?acm=3.mce.2_10_1ji16.43542.0.ccy5br4OlfK0R.pos_1-m_454889-sd_119",
            "title": "入秋穿搭指南",
            "width": 750,
            "width923": 750
          },
          {
            "acm": "3.mce.2_10_1jfj8.43542.0.ccy5br4OlfK0S.pos_2-m_453270-sd_119",
            "height": 390,
            "height923": 390,
            "image": "https://s10.mogucdn.com/mlcdn/c45406/180919_3f62ijgkj656k2lj03dh0di4iflea_750x390.jpg",
            "image923": "https://s10.mogucdn.com/mlcdn/c45406/180919_47iclhel8f4ld06hid21he98i93fc_750x390.jpg",
            "link": "https://act.mogujie.com/huanji001?acm=3.mce.2_10_1jfj8.43542.0.ccy5br4OlfK0S.pos_2-m_453270-sd_119",
            "title": "秋季护肤大作战",
            "width": 750,
            "width923": 750
          },
          {
            "acm": "3.mce.2_10_1jepe.43542.0.ccy5br4OlfK0T.pos_3-m_452733-sd_119",
            "height": 390,
            "height923": 390,
            "image": "https://s10.mogucdn.com/mlcdn/c45406/180917_18l981g6clk33fbl3833ja357aaa0_750x390.jpg",
            "image923": "https://s10.mogucdn.com/mlcdn/c45406/180917_0hgle1e2c350a57ekhbj4f10a6b03_750x390.jpg",
            "link": "https://act.mogujie.com/liuxing00001?acm=3.mce.2_10_1jepe.43542.0.ccy5br4OlfK0T.pos_3-m_452733-sd_119",
            "title": "流行抢先一步",
            "width": 750,
            "width923": 750
          }
        ],
        "nextPage": 1
      }
    }

XHR-XHR请求的基本使用

1

javascript 复制代码
 // 1.创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    // 2.监听状态的改变(宏任务)
    xhr.onreadystatechange = function() {
      // console.log(xhr.response)
      if (xhr.readyState !== XMLHttpRequest.DONE) return

      // 将字符串转成JSON对象(js对象)
      const resJSON = JSON.parse(xhr.response)
      const banners = resJSON.data.banner.list
      console.log(banners)
    }

    // 3.配置请求open
    // method: 请求的方式(get/post/delete/put/patch...)
    // url: 请求的地址
    xhr.open("get", "http://123.207.32.32:8000/home/multidata")

    // 4.发送请求(浏览器帮助发送对应请求)
    xhr.send()

XHR-XHR状态变化的监听

这里发送的是异步请求,并且可以拿到状态码,4种状态码对应不同的事件。

javascript 复制代码
 // 1.创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    // 2.监听状态的改变(宏任务)
    // 监听四种状态
    xhr.onreadystatechange = function() {
      // 1.如果状态不是DONE状态, 直接返回
      if (xhr.readyState !== XMLHttpRequest.DONE) return

      // 2.确定拿到了数据
      console.log(xhr.response)
    }

    // 3.配置请求open
    xhr.open("get", "http://123.207.32.32:8000/home/multidata")

    // 4.发送请求(浏览器帮助发送对应请求)
    xhr.send()

XHR-XHR发送同步的请求


open的第三个参数可以设置是否是异步请求,设置false就是改变成同步请求,只有服务器返回浏览器有接过来才会执行后续的代码。

javascript 复制代码
 // 1.创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    // 2.监听状态的改变(宏任务)
    // 监听四种状态
    // xhr.onreadystatechange = function() {
    //   // 1.如果状态不是DONE状态, 直接返回
    //   if (xhr.readyState !== XMLHttpRequest.DONE) return

    //   // 2.确定拿到了数据
    //   console.log(xhr.response)
    // }

    // 3.配置请求open
    // async: false
    // 实际开发中要使用异步请求, 异步请求不会阻塞js代码继续执行
    xhr.open("get", "http://123.207.32.32:8000/home/multidata", false)

    // 4.发送请求(浏览器帮助发送对应请求)
    xhr.send()

    // 5.同步必须等到有结果后, 才会继续执行
    console.log(xhr.response)

    console.log("------")
    console.log("++++++")
    console.log("******")

XHR-XHR其他事件的监听

函数的调用方式不同。

javascript 复制代码
   const xhr = new XMLHttpRequest()
    // onload监听数据加载完成
    xhr.onload = function() {
      console.log("onload")
    }
    xhr.open("get", "http://123.207.32.32:8000/home/multidata")
    xhr.send()

XHR-XHR响应数据和类型

告知xhr获取到的数据的类型

xhr.responseType = "json"

javascript 复制代码
    // 1.
    const xhr = new XMLHttpRequest()

    // 2.onload监听数据加载完成
    xhr.onload = function() {
      // const resJSON = JSON.parse(xhr.response)
      console.log(xhr.response)
      // console.log(xhr.responseText)
      // console.log(xhr.responseXML)
    }

    // 3.告知xhr获取到的数据的类型
    xhr.responseType = "json"
    // xhr.responseType = "xml"

    // 4.配置网络请求
    // 4.1.json类型的接口
    xhr.open("get", "http://123.207.32.32:8000/home/multidata")
    // 4.2.json类型的接口
    // xhr.open("get", "http://123.207.32.32:1888/01_basic/hello_json")
    // 4.3.text类型的接口
    // xhr.open("get", "http://123.207.32.32:1888/01_basic/hello_text")
    // 4.4.xml类型的接口
    // xhr.open("get", "http://123.207.32.32:1888/01_basic/hello_xml")

    // 5.发送网络请求
    xhr.send()

XHR-获取HTTP的状态码

xhr.status

javascript 复制代码
 // 1.创建对象
    const xhr = new XMLHttpRequest()

    // 2.监听结果
    xhr.onload = function() {
      console.log(xhr.status, xhr.statusText)
      // 根据http的状态码判断是否请求成功
      if (xhr.status >= 200 && xhr.status < 300) {
        console.log(xhr.response)
      } else {
        console.log(xhr.status, xhr.statusText)
      }
    }

    xhr.onerror = function() {
      console.log("onerror", xhr.status, xhr.statusText)
    }

    // 3.设置响应类型
    xhr.responseType = "json"

    // 4.配置网络请求
    // xhr.open("get", "http://123.207.32.32:8000/abc/cba/aaa")
    xhr.open("get", "http://123.207.32.32:8000/home/multidata")

    // 5.发送网络请求
    xhr.send()

XHR-GET-POST请求传参

1

javascript 复制代码
 const formEl = document.querySelector(".info")
    const sendBtn = document.querySelector(".send")
    sendBtn.onclick = function() {
      // 创建xhr对象
      const xhr = new XMLHttpRequest()

      // 监听数据响应
      xhr.onload = function() {
        console.log(xhr.response)
      }

      // 配置请求
      xhr.responseType = "json"

      // 1.传递参数方式一: get -> query
      // xhr.open("get", "http://123.207.32.32:1888/02_param/get?name=why&age=18&address=广州市")

      // 2.传递参数方式二: post -> urlencoded
      // xhr.open("post", "http://123.207.32.32:1888/02_param/posturl")
      // // 发送请求(请求体body)
      // xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
      // xhr.send("name=why&age=18&address=广州市")

      // 3.传递参数方式三: post -> formdata
      // xhr.open("post", "http://123.207.32.32:1888/02_param/postform")
      // // formElement对象转成FormData对象
      // const formData = new FormData(formEl)
      // xhr.send(formData)

      // 4.传递参数方式四: post -> json
      xhr.open("post", "http://123.207.32.32:1888/02_param/postjson")
      xhr.setRequestHeader("Content-type", "application/json")
      xhr.send(JSON.stringify({name: "why", age: 18, height: 1.88}))
    }

XHR-Ajax网络请求封装

1

javascript 复制代码
 // 练习hyajax -> axios
    function hyajax({
      url,
      method = "get",
      data = {},
      headers = {}, // token
      success,
      failure
    } = {}) {
      // 1.创建对象
      const xhr = new XMLHttpRequest()

      // 2.监听数据
      xhr.onload = function() {
        if (xhr.status >= 200 && xhr.status < 300) {
          success && success(xhr.response)
        } else {
          failure && failure({ status: xhr.status, message: xhr.statusText })
        }
      }

      // 3.设置类型
      xhr.responseType = "json"

      // 4.open方法
      if (method.toUpperCase() === "GET") {
        const queryStrings = []
        for (const key in data) {
          queryStrings.push(`${key}=${data[key]}`)
        }
        url = url + "?" + queryStrings.join("&")
        xhr.open(method, url)
        xhr.send()
      } else {
        xhr.open(method, url)
        xhr.setRequestHeader("Content-type", "application/json")
        xhr.send(JSON.stringify(data))
      }

      return xhr
    }

    // 调用者
    hyajax({
      url: "http://123.207.32.32:1888/02_param/get",
      method: "GET",
      data: {
        name: "why",
        age: 18
      },
      success: function(res) {
        console.log("res:", res)
      },
      failure: function(err) {
        // alert(err.message)
      }
    })

    // hyajax({
    //   url: "http://123.207.32.32:1888/02_param/postjson",
    //   method: "post",
    //   data: {
    //     name: "jsondata",
    //     age: 22
    //   },
    //   success: function(res) {
    //     console.log("res:", res)
    //   },
    //   failure: function(err) {
    //     // alert(err.message)
    //   }
    // })

XHR-Ajax网络请求工具

hyajax_promise.js

javascript 复制代码
// 练习hyajax -> axios
function hyajax({
  url,
  method = "get",
  data = {},
  timeout = 10000,
  headers = {}, // token
} = {}) {
  // 1.创建对象
  const xhr = new XMLHttpRequest()

  // 2.创建Promise
  const promise = new Promise((resolve, reject) => {

    // 2.监听数据
    xhr.onload = function() {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(xhr.response)
      } else {
        reject({ status: xhr.status, message: xhr.statusText })
      }
    }

    // 3.设置类型
    xhr.responseType = "json"
    xhr.timeout = timeout

    // 4.open方法
    if (method.toUpperCase() === "GET") {
      const queryStrings = []
      for (const key in data) {
        queryStrings.push(`${key}=${data[key]}`)
      }
      url = url + "?" + queryStrings.join("&")
      xhr.open(method, url)
      xhr.send()
    } else {
      xhr.open(method, url)
      xhr.setRequestHeader("Content-type", "application/json")
      xhr.send(JSON.stringify(data))
    }
  })

  promise.xhr = xhr

  return promise
}

hyajax.js

javascript 复制代码
// 练习hyajax -> axios
function hyajax({
  url,
  method = "get",
  data = {},
  timeout = 10000,
  headers = {}, // token
  success,
  failure
} = {}) {
  // 1.创建对象
  const xhr = new XMLHttpRequest()

  // 2.监听数据
  xhr.onload = function() {
    if (xhr.status >= 200 && xhr.status < 300) {
      success && success(xhr.response)
    } else {
      failure && failure({ status: xhr.status, message: xhr.statusText })
    }
  }

  // 3.设置类型
  xhr.responseType = "json"
  xhr.timeout = timeout

  // 4.open方法
  if (method.toUpperCase() === "GET") {
    const queryStrings = []
    for (const key in data) {
      queryStrings.push(`${key}=${data[key]}`)
    }
    url = url + "?" + queryStrings.join("&")
    xhr.open(method, url)
    xhr.send()
  } else {
    xhr.open(method, url)
    xhr.setRequestHeader("Content-type", "application/json")
    xhr.send(JSON.stringify(data))
  }

  return xhr
}
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <!-- <script src="./utils/hyajax.js"></script> -->
  <script src="./utils/hyajax_promise.js"></script>
  <script>
    const promise = hyajax({
      url: "http://123.207.32.32:1888/02_param/get",
      data: {
        username: "coderwhy",
        password: "123456"
      }
    })

    promise.then(res => {
      console.log("res:", res)
    }).catch(err => {
      console.log("err:", err)
    })
  </script>
</body>
</html>

XHR-超时时间-取消请求

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <button>取消请求</button>

  <script>
    const xhr = new XMLHttpRequest()

    xhr.onload = function() {
      console.log(xhr.response)
    }
    xhr.onabort = function() {
      console.log("请求被取消掉了")
    }
    
    xhr.responseType = "json"

    // 1.超市时间的设置
    xhr.ontimeout = function() {
      console.log("请求过期: timeout")
    }
    // timeout: 浏览器达到过期时间还没有获取到对应的结果时, 取消本次请求
    // xhr.timeout = 3000
    xhr.open("get", "http://123.207.32.32:1888/01_basic/timeout")

    xhr.send()

    // 2.手动取消结果
    const cancelBtn = document.querySelector("button")
    cancelBtn.onclick = function() {
      xhr.abort()
    }

  </script>

</body>
</html>

Fetch-Fetch函数基本使用

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>

    // 1.fetch发送get请求
    // 1.1.未优化的代码
    // fetch("http://123.207.32.32:8000/home/multidata").then(res => {
    //   // 1.获取到response
    //   const response = res

    //   // 2.获取具体的结果
    //   response.json().then(res => {
    //     console.log("res:", res)
    //   })
    // }).catch(err => {
    //   console.log("err:", err)
    // })

    // 1.2. 优化方式一:
    // fetch("http://123.207.32.32:8000/home/multidata").then(res => {
    //   // 1.获取到response
    //   const response = res
    //   // 2.获取具体的结果
    //   return response.json()
    // }).then(res => {
    //   console.log("res:", res)
    // }).catch(err => {
    //   console.log("err:", err)
    // })

    // 1.3. 优化方式二:
    // async function getData() {
    //   const response = await fetch("http://123.207.32.32:8000/home/multidata")
    //   const res = await response.json()
    //   console.log("res:", res)
    // }
    // getData()


    // 2.post请求并且有参数
    async function getData() {
      // const response = await fetch("http://123.207.32.32:1888/02_param/postjson", {
      //   method: "post",
      //   // headers: {
      //   //   "Content-type": "application/json"
      //   // },
      //   body: JSON.stringify({
      //     name: "why",
      //     age: 18
      //   })
      // })
      
      const formData = new FormData()
      formData.append("name", "why")
      formData.append("age", 18)
      const response = await fetch("http://123.207.32.32:1888/02_param/postform", {
        method: "post",
        body: formData
      })

      // 获取response状态
      console.log(response.ok, response.status, response.statusText)

      const res = await response.json()
      console.log("res:", res)
    }
    getData()

  </script>

</body>
</html>

XHR-文件上传的接口演练

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <input class="file" type="file">
  <button class="upload">上传文件</button>
  
  <script>

    // xhr/fetch

    const uploadBtn = document.querySelector(".upload")
    uploadBtn.onclick = function() {
      // 1.创建对象
      const xhr = new XMLHttpRequest()

      // 2.监听结果
      xhr.onload = function() {
        console.log(xhr.response)
      }

      xhr.onprogress = function(event) {
        console.log(event)
      }
      

      xhr.responseType = "json"
      xhr.open("post", "http://123.207.32.32:1888/02_param/upload")

      // 表单
      const fileEl = document.querySelector(".file")
      const file = fileEl.files[0]

      const formData = new FormData()
      formData.append("avatar", file)

      xhr.send(formData)
    }
  </script>

</body>
</html>

Fetch-文件上传的接口演练

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <input class="file" type="file">
  <button class="upload">上传文件</button>
  
  <script>

    // xhr/fetch

    const uploadBtn = document.querySelector(".upload")
    uploadBtn.onclick = async function() {
      // 表单
      const fileEl = document.querySelector(".file")
      const file = fileEl.files[0]

      const formData = new FormData()
      formData.append("avatar", file)

      // 发送fetch请求
      const response = await fetch("http://123.207.32.32:1888/02_param/upload", {
        method: "post",
        body: formData
      })
      const res = await response.json()
      console.log("res:", res)
    }

  </script>

</body>
</html>
相关推荐
我命由我123455 分钟前
React - state、state 的简写方式、props、props 的简写方式、类式组件中的构造器与 props、函数式组件使用 props
前端·javascript·react.js·前端框架·html·html5·js
钰衡大师7 分钟前
Vue 3 源码学习教程
前端·vue.js·学习
C澒8 分钟前
React + TypeScript 编码规范|统一标准 & 高效维护
前端·react.js·typescript·团队开发·代码规范
时光少年25 分钟前
Android 视频分屏性能优化——GLContext共享
前端
IT_陈寒42 分钟前
JavaScript开发者必知的5个性能杀手,你踩了几个坑?
前端·人工智能·后端
跟着珅聪学java1 小时前
Electron 精美菜单设计
运维·前端·数据库
日光倾1 小时前
【Vue.js 入门笔记】闭包和对象引用
前端·vue.js·笔记
EstherNi1 小时前
左右两侧定位的效果,vue3
javascript·vue.js
一只程序熊1 小时前
UniappX 未找到 “video“ 组件,已自动当做 “view“ 组件处理。请确保代码正确,或重新生成自定义基座后再试。
前端
林小帅1 小时前
【笔记】xxx 技术分享文档模板
前端