自学内容网 自学内容网

Ajax学习笔记


Ajax学习笔记

定义:Ajax是异步的JavaScript和XML。简单来说就是使用XMLHttpRequest对象与服务器通信。它可以使用JSON、XML、HTML和text文本邓格式发送和接收数据。Ajax最吸引人的就是它的“异步”特性,也就是说它可以在不重新刷新页面的情况下与服务器通信、交换数据或更新页面。

概念:Ajax是浏览器与服务器进行数据通信的技术。

作用:浏览器和服务器之间通信,动态数据交互。

axios使用

axios体验步骤:

  • 引用axios库
  • 使用axios语法
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <p class="my-p"></p>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    axios({
      url: 'https://hmajax.itheima.net/api/province'
    }).then(result => {
      //console.log(result.data.list.join(`<br>`));
      document.querySelector('.my-p').innerHTML = result.data.list.join(`<br>`)
    })
  </script>
</body>

</html>

axios请求拦截器

axios请求拦截器:发起请求之前,出发点配置函数,对请求参数进行额外配置。

语法:

axios.interceptors.request.use(function (config) {
    // 在发送请求之前做什么
    return config
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error)
})

axios响应拦截器

axios响应拦截器:响应回到then/catch之前,触发的拦截函数,对响应的结果统一处理。

语法:

axios.interceptors.response.use(function (response) {
  // 2xx范围内的状态码都会触发该函数
  // 对响应数据做些什么
  return response
}, function (error) {
  // 超出2xx范围的状态码都会触发该函数
  // 对响应错误做点什么。
  return Promise.reject(error)
})

优化axios响应结果

目标:axios直接接收服务器返回的响应结果。

form-serialize插件

作用:快速收集表单元素的值。

语法:serialize(form, { hash: true, empty: true })

  • form:获取的表单
  • hash:设置获取数据结构
    • true:JS对象
    • false:查询字符串
  • empty:设置是否获取空值
    • true:获取空值,使数据结构和标签结构一致
    • false:不获取空值
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <form action="javascript:;">
    <input type="text" name="username">
    <br>
    <input type="text" name="password">
    <br>
    <input type="button" class="btn" value="提交">
  </form>
  <script src="../form-serialize.js"></script>
  <script>
    document.querySelector('.btn').addEventListener('click', () => {
      const form = document.querySelector('form')
      const data = serialize(form, { hash: true, empty: true })
      console.log(data);
    })
  </script>
</body>

</html>

图片上传

使用步骤:

  1. 获取图片文件对象

  2. 使用FormData携带图片文件

    const fd = new FormmData()
    fd.append(参数名,)
    
  3. 提交表单数据到服务器,使用图片url网址

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file" class="upload">
  <img src="" alt="">
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    document.querySelector('.upload').addEventListener('change', e => {
      console.log(e.target.files[0]);
      const fd = new FormData()
      fd.append('img', e.target.files[0])
      axios({
        url: 'http://hmajax.itheima.net/api/uploadimg',
        method: 'post',
        data: fd
      }).then(result => {
        const imgurl = result.data.data.url
        document.querySelector('img').src = imgurl
      })
    })
  </script>
</body>

</html>

HTTP协议

HTTM协议:规定了浏览器发送及服务器返回内容的格式。

请求报文

请求报文:浏览器按照HTTP协议要求的格式,发送给服务器的内容。

组成部分:

  1. 请求行:请求方法,URL,协议
  2. 请求头:以键值对的格式携带的附加信息,比如Content-Type
  3. 空行:分隔请求头,空行之后的是发送给服务器的资源
  4. 请求体:发送的资源

相应报文

响应报文:服务器按照HTTP协议要求的格式,返回给浏览器的内容。

组成部分:

  1. 响应行(状态行):协议、HTTP响应状态码、状态信息

    • HTTP响应状态码:用来表明请求释放成功完成

    • 状态码说明
      1xx信息
      2xx成功
      3xx重定向信息
      4xx客户端错误
      5xx服务端错误
    • 比如:404(服务器找不到资源)

  2. 响应头:以键值对的格式携带的附加信息,比如Content-Type

  3. 空行:分隔响应头,空行之后是服务器返回的资源

  4. 响应体:返回的资源

接口文档

接口文档:描述接口的文章。

接口:使用AJAX和服务器通讯时,使用的URL、请求方法以及参数。

AJAX原理 - XMLHttpRequest

定义:XMLHttpRequest(XHG)对象用于与服务器交互。通过XMLHttpRequest可以在不刷新页面的情况下请求特定URL,获取数据。这允许网页在不影响用户操作的情况下,更新网页的局部内容。

关系:axios内部采用XMLHttpRequest与服务器交互

使用XMLHttpRequest

使用步骤:

  1. 创建XMLHttpRequest对象

  2. 配置请求方法和请求url地址

  3. 监听loadend事件,接收响应结果

  4. 发起请求

        const xhr = new XMLHttpRequest()
        xhr.open('请求方法', '请求url网址')
        xhr.addEventListener('loadend', () => {
          console.log(xhr.response)
        })
    

XMLHttpRequest - 查询参数

定义:浏览器提供给服务器的额外信息,让服务器返回浏览器想要的数据。

例子:查询河北省的城市名称。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div></div>
  <script>
    const xhr = new XMLHttpRequest()
    xhr.open('get', 'https://hmajax.itheima.net/api/city?pname=河北省')
    xhr.addEventListener('loadend', () => {
      console.log(xhr.response);
      // 将字符串转成对象
      const data = JSON.parse(xhr.response) // 字符串转对象
      document.querySelector('div').innerHTML = data.list.join('<br>')
    })
    xhr.send()
  </script>
</body>

</html>
查询字符串对象

使用步骤:

  1. 创建URLSearchParams对象
  2. 生成固定格式查询参数的字符串
    const paramsobj = new URLSearchParams({
      参数名1:1,
      参数名2:2
    })
    const queryString = paramsobj.toString() // 结果:参数名1=值1&参数名2=值2

XMLHttpRequest - 数据提交

核心:

  • 请求头设置Content-Type:application/json
  • 请求体携带JSON字符串
    const xhr = new XMLHttpRequest()
    xhr.open('请求方法', '请求url网址')
    xhr.addEventListener('loadend', () => {
      console.log(xhr.response);
    })
    // 告诉服务器,传递的内容类型,是JSON字符串
    xhr.setRequestHeader('Content-Type', 'application/json')
    // 准备数据并转成JSON字符串
    const user = { username: 'itheima007', password: '7654321' }
    const userStr = JSON.stringify(user)
    xhr.send(userStr) // 发送请求体数据

事件循环

概念:JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。

原因:JavaScript单线程(某一时刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环。

执行过程

定义:执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环。

    console.log(1);
    setTimeout(() => {
      console.log(2);
    }, 2000)
    console.log(3);
    setTimeout(() => {
      console.log(4);
    }, 0)
    console.log(5);
    // 打印顺序:1 3 5 4 2

宏任务和微任务

ES6之后引入了Promise对象,让JS引擎也可以发起异步任务。

异步任务分为:

  • 宏任务:由浏览器环境执行的异步代码
  • 微任务:由JS引擎环境执行的异步代码
任务(代码)执行所在环境
JS脚本执行事件(script)浏览器
setTimeout/setInterval浏览器
AJAX请求完成事件浏览器
用户交互完成事件浏览器
Promise对象.then()JS引擎

Promise本身是同步的,而then和catch回调函数是异步的。

因为微任务队列离JS引擎更近,所以先执行微任务队列里的代码,再执行宏任务队列里的代码。

    console.log(1);
    setTimeout(() => {
      console.log(2);
    })
    const p = new Promise((resolve, reject) => {
      console.log(3);
      resolve(4)
    })
    p.then(result => {
      console.log(result);
    })
    console.log(5);
    // 打印顺序:1 3 5 4 2
    console.log(1)
    setTimeout(() => {
      console.log(2)
      const p = new Promise(resolve => resolve(3))
      p.then(result => console.log(result))
    }, 0)
    const p = new Promise(resolve => {
      setTimeout(() => {
        console.log(4)
      }, 0)
      resolve(5)
    })
    p.then(result => console.log(result))
    const p2 = new Promise(resolve => resolve(6))
    p2.then(result => console.log(result))
    console.log(7)
    // 1 7 5 6 2 3 4

Promise对象

定义:Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值。

好处:

  • 使逻辑更清晰
  • 了解axios函数内部运作机制
  • 能解决回调函数地狱问题

核心代码:

    // 1.创建promise对象
    const p = new Promise((resolve, reject) => {
      // 2.执行异步任务并传递结果
      // 成功调用:resolve(值) 触发then()执行
      // 失败调用:reject(值) 触发catch()执行
    })
    // 3.接收结果
    p.then(result => {
      // 成功
    }).catch(error => {
      // 失败
    })

同步代码和异步代码

同步代码:逐步执行,需要原地等待结果后,才继续往下执行。

异步代码:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数。

JS中的异步代码:

  • setTimeout / setInterval
  • 事件
  • AJAX

异步代码通过回调函数接受结果。

回调函数地狱

概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱。

缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身。

Promise的三种状态

作用:了解Promise对象如何关联的处理函数,以及代码执行顺序。

概念:一个Promise对象,必定处于以下三种状态之中:

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝
  • 已兑现(fulfilled):操作成功完成
  • 已拒绝(rejected):操作失败

注意:

  • promise对象一旦被兑现/拒绝,就是已敲定了,状态无法再被改变。
  • new promise()里的回调函数会立即执行

通过Promise+XHR模拟axios实现

需求:基于Promise+XHR封装myAxios函数,获取省份列表展示

步骤:

  1. 定义myAxios函数,接收配置对象,返回Promise对象
  2. 发起XHR请求,默认请求方法为get
  3. 调用成功/失败的处理程序
  4. 使用myAxios函数,获取省份列表展示

核心代码模板:

    function myAxios (config){
      return new Promise((resolve, reject) => {
        // XHR请求
        // 调用成功/失败的处理程序
      })
    }
    myAxios({
      url: '目标资源地址'
    }).then(result => {

    }).catch(error => {
      
    })

完整实现代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <p></p>
  <script>
    function myAxios(config) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.open(config.method || 'get', config.url)
        xhr.addEventListener('loadend', () => {
          if (xhr.status >= 200 && xhr.status < 300) {
            resolve(JSON.parse(xhr.response))
          }
          else {
            reject(new Error(xhr.response))
          }
        })
        xhr.send()
      })
    }

    myAxios({
      url: 'https://hmajax.itheima.net/api/province'
    }).then(result => {
      console.log(result);
      document.querySelector('p').innerHTML = result.list.join('<br>')
    }).catch(error => {
      console.log(error);
      document.querySelector('p').innerHTML = error.message
    })
  </script>
</body>

</html>

Promise - 链式调用

概念:依靠then()方法会返回一个新生成的Promise对象特性,继续串联下一环任务,直到结束。

细节:then()回调函数中的返回值,会影响新生成的Promise对象的最终状态和结果

好处:通过链式调用,解决回调函数嵌套问题。

链式调用解决回调函数地狱:省份——城市——地区查询
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    let pname = ''
    const p = axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
      pname = result.data.list[0]
      document.querySelector('.a').innerHTML = pname
      return axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
    }).then(result => {
      const cname = result.data.list[0]
      document.querySelector('.b').innerHTML = cname
      return axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
    }).then(result => {
      const areaName = result.data.list[0]
      document.querySelector('.c').innerHTML = areaName
    })
  </script>
</body>

</html>


Promise.all 静态方法

概念:合并多个Promise对象,等待所有同时成功完成(或某一个失败),做后续逻辑。

需求:当需要同一时间显示多个请求时,就需要把多请求合并。

语法:const p = Promise.all([对象1, 对象2, ...])

async函数和await关键字

定义:asyn和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用Promise。

概念:在async函数内,使用await关键字取代then函数,等待获取Promise对象成功状态的结果值。

使用async函数和await关键字解决回调函数地狱

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    async function getData() {
      const pobj = await axios({ url: 'http://hmajax.itheima.net/api/province' })
      const pname = pobj.data.list[0]
      const cobj = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
      const cname = cobj.data.list[0]
      const aobj = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
      const areaName = aobj.data.list[0]

      document.querySelector('.a').innerHTML = pname
      document.querySelector('.b').innerHTML = cname
      document.querySelector('.c').innerHTML = areaName
    }
    getData()
  </script>
</body>

</html>

async函数和await关键字的错误捕获

使用try…catch语句标记要尝试捕获的语句块,并指定一个出现异常时抛出的响应。

语法:

try {
    // 要执行的代码
} catch(error) {
    // error接收的是错误信息
    // try里代码,如果有错误,直接进入这里执行
}
    async function getData() {
      try {
        const pobj = await axios({ url: 'http://hmajax.itheima.net/api/province' })
        const pname = pobj.data.list[0]
        const cobj = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
        const cname = cobj.data.list[0]
        const aobj = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
        const areaName = aobj.data.list[0]

        document.querySelector('.a').innerHTML = pname
        document.querySelector('.b').innerHTML = cname
        document.querySelector('.c').innerHTML = areaName
      } catch (error) {
        console.dir(error)
      }
    }
    getData()

原文地址:https://blog.csdn.net/2301_79614379/article/details/140589618

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!