AJAX 进阶 day4

news2024/11/13 9:34:21

目录

1.同步代码和异步代码

2.回调函数地狱和 Promise 链式调用

2.1 回调函数地狱

2.2 Promise - 链式调用

2.3 Promise 链式应用

3.async 和 await 使用

3.1 async函数和await

3.2 async函数和await_捕获错误

4.事件循环-EventLoop

4.1 事件循环

4.2 宏任务与微任务- 执行顺序

4.3 总结

5.Promise.all 静态方法

6.案例 - 商品分类

7.案例 - 学习反馈

7.1 完成省市区切换效果

7.2 收集学习反馈数据,提交保存


1.同步代码和异步代码

                                                                                                

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

小结:

1. 什么是同步代码?
        ➢ 逐行执行, 原地等待 结果 后,才继续向下执行
2. 什么是异步代码?
        ➢ 调用后 耗时 ,不阻塞代码执行,将来完成后触发 回调函数
3. JS 中有哪些异步代码?
        ➢ setTimeout / setInterval
        ➢ 事件
        ➢ AJAX
4. 异步代码如何接收结果?
        ➢ 依靠 回调函数 来接收

2.回调函数地狱和 Promise 链式调用

2.1 回调函数地狱

概念:在回调函数中 嵌套回调函数 ,一直嵌套下去就形成了回调函数地狱
缺点:可读性差,异常无法捕获(内层的错误信息,外层无法捕获),耦合性严重,牵一发动全身

案例:

需求:展示默认第一个省,第一个城市,第一个地区在下拉菜单中

2.2 Promise - 链式调用

概念:依靠 then() 方法会返回一个 新生成的 Promise 对象 特性,继续串联下一环任务,直到结束
细节:then() 回调函数中的 返回值 ,会影响新生成的 Promise 对象 最终状态和结果
好处:通过链式调用,解决回调函数嵌套问题

2.3 Promise 链式应用

目标:使用 Promise 链式调用,解决回调函数地狱问题
做法:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来

代码:

<script>
    /**
     * 目标:把回调函数嵌套代码,改成Promise链式调用结构
     * 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中
    */
    let pname = ''

    axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
      // 获取第一个省份
      // console.log(result.data.list[0])
      const province = document.querySelector('.province')
      pname = result.data.list[0]
      province.innerHTML = result.data.list[0]
      // 返回城市的对象
      return axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
    }).then(result => {
      // console.log(result.data.list[0])
      // 获取第一个城市
      const city = document.querySelector('.city')
      const cname = result.data.list[0]
      city.innerHTML = result.data.list[0]
      // 返回地区信息
      return axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
    }).then(result => {
      // 获取第一个地区
      const area = document.querySelector('.area')
      area.innerHTML = result.data.list[0]
    })
  </script>

小结:

1. 什么是 Promise 的链式调用?
        ➢ 使用 then 方法返回新 Promise 对象特性,一直串联下去
2. then 回调函数中,return 的值会传给哪里?
        ➢ 传给 then 方法生成的新 Promise 对象
3. Promise 链式调用有什么用?
        ➢ 解决回调函数嵌套问题

        

3.async 和 await 使用

3.1 async函数和await

目标:掌握async和await语法,解决回调函数地狱

定义:

async 函数是 JavaScript 的一种特殊函数,它可以在函数中使用 await 关键字。当你将一个普通函数用 async 关键字修饰后,这个函数默认返回一个 Promise 对象。普通的返回值会被封装成一个 fulfilled 状态的 Promise 对象,而抛出的任何异常都会被封装成 rejected 状态的 Promise 对象。

概念:在async函数内,使用await关键字,获取Promise对象 "成功状态"结果值

注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)

代码:

<script>
    /**
     * 目标:掌握async和await语法,解决回调函数地狱
     * 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值
     * 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)
    */

    async function getData() {
      const p = await axios({ url: 'http://hmajax.itheima.net/api/province' })
      const pname = p.data.list[0]
      // console.log(p.data.list[0])
      const c = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
      const cname = c.data.list[0]
      // console.log(c.data.list[0])
      const a = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
      const aname = a.data.list[0]
      console.log(a)

      // 写入html文档
      document.querySelector('.province').innerHTML = pname
      document.querySelector('.city').innerHTML = cname
      document.querySelector('.area').innerHTML = aname

    }

    getData()
  </script>

3.2 async函数和await_捕获错误

语法:
代码:
<script>
    /**
     * 目标:掌握async和await语法,解决回调函数地狱
     * 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值
     * 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)
    */

    async function getData() {
      try {
        const p = await axios({ url: 'http://hmajax.itheima.net/api/province' })
        const pname = p.data.list[0]
        // console.log(p.data.list[0])
        const c = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
        const cname = c.data.list[0]
        // console.log(c.data.list[0])
        const a = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
        const aname = a.data.list[0]
        console.log(a)

        // 写入html文档
        document.querySelector('.province').innerHTML = pname
        document.querySelector('.city').innerHTML = cname
        document.querySelector('.area').innerHTML = aname

      } catch (error) {
        console.dir(error)
      }
    }

    getData()
  </script>

捕捉到异常之后,异常后面的代码将不再执行。

4.事件循环-EventLoop

4.1 事件循环

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

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

原理:

  1. 调用栈(Call Stack)

    • 调用栈是执行代码的地方。它记录了当前正在执行的函数和函数调用的历史。当一个函数被调用时,它会被压入调用栈中,执行完成后,它会被从栈中弹出。
  2. 任务队列(Task Queue 或 Callback Queue)

    • 任务队列用于存放异步任务的回调函数。例如,当 setTimeout 函数的定时器结束时,它的回调函数会被放到任务队列中。
  3. 微任务队列(Microtask Queue)

    • 微任务队列存放的是微任务(例如 Promise 的回调函数)。微任务通常比宏任务(如定时器回调)优先级更高。微任务队列的任务会在事件循环的每一轮结束之前执行完毕。

4.2 宏任务与微任务- 执行顺序

异步任务分为:
  • 宏任务:由浏览器环境执行的异步代码
  • 微任务:由 JS 引擎环境执行的异步代码

执行顺序:

使用图解-分析代码执行顺序

简单理解:同步就是会被立即执行的代码,而异步会被分配到相应的任务队列进行等待,

当栈处于空闲状态就会先清空微任务队列,再执行宏任务队列。

4.3 总结

1. 什么是宏任务?
  • 浏览器执行的异步代码
  • 例如:JS 执行脚本事件,setTimeout/setInterval,AJAX请求完成 事件,用户交互事件等
2. 什么是微任务?
  • JS 引擎执行的异步代码
  • 例如:Promise对象.then()的回调
3. JavaScript 内代码如何执行?
  • 执行第一个 script 脚本事件宏任务,里面同步代码
  • 遇到 宏任务/微任务 交给宿主环境,有结果回调函数进入对应队列
  • 当执行栈空闲时,清空微任务队列,再执行下一个宏任务,从1再来

5.Promise.all 静态方法

概念:合并多个 Promise 对象,等待所有 同时成功 完成(或某一个失败),做后续逻辑 。
语法:
需求:同时请求“北京”,“上海”,“广州”,“深圳”的天气并在网页尽可能 同时 显示
代码演示:
<body>
  <ul class="my-ul"></ul>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /**
     * 目标:掌握Promise的all方法作用,和使用场景
     * 业务:当我需要同一时间显示多个请求的结果时,就要把多请求合并
     * 例如:默认显示"北京", "上海", "广州", "深圳"的天气在首页查看
     * code:
     * 北京-110100
     * 上海-310100
     * 广州-440100
     * 深圳-440300
    */
    // 1. 请求城市天气,得到Promise对象
    const bjPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '110100' } })
    const shPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '310100' } })
    const gzPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440100' } })
    const szPromise = axios({ url: 'http://hmajax.itheima.net/api/weather', params: { city: '440300' } })

    // 2. 使用Promise.all,合并多个Promise对象
    const p = Promise.all([bjPromise, shPromise, gzPromise, szPromise])
    p.then(result => {
      // 注意:结果数组顺序和合并时顺序是一致
      console.log(result)
      const htmlStr = result.map(item => {
        return `<li>${item.data.data.area} --- ${item.data.data.weather}</li>`
      }).join('')
      document.querySelector('.my-ul').innerHTML = htmlStr
    }).catch(error => {
      console.dir(error)
    })
  </script>
</body>

6.案例 - 商品分类

商品分类

需求:尽可能同时展示所有商品分类到页面上
步骤:
  • 1. 获取所有的一级分类数据
  • 2. 遍历id,创建获取二级分类请求
  • 3. 合并所有二级分类Promise对象
  • 4. 等待同时成功,开始渲染页面

效果图:

代码:

<body>
  <!-- 大容器 -->
  <div class="container">
    <div class="sub-list">
      <div class="item">
        <h3>分类名字</h3>
        <ul>
          <li>
            <a href="javascript:;">
              <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
              <p>巧克力</p>
            </a>
          </li>
          <li>
            <a href="javascript:;">
              <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
              <p>巧克力</p>
            </a>
          </li>
          <li>
            <a href="javascript:;">
              <img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
              <p>巧克力</p>
            </a>
          </li>
        </ul>
      </div>
    </div>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script>
    /**
     * 目标:把所有商品分类“同时”渲染到页面上
     *  1. 获取所有一级分类数据
     *  2. 遍历id,创建获取二级分类请求
     *  3. 合并所有二级分类Promise对象
     *  4. 等待同时成功后,渲染页面
    */
    axios({
      url: 'http://hmajax.itheima.net/api/category/top'
    }).then(result => {
      // 获取所有一级分类数据
      console.log(result.data.data)

      // 遍历id,创建获取二级分类请求, 这里得到的是所有二级分类的promise对象数组
      const firstObj = result.data.data.map(item => {
        // console.log(item.id)
        return axios({
          url: 'http://hmajax.itheima.net/api/category/sub',
          params: { id: item.id }
        })
      })

      // console.log(firstObj)
      // 合并所有二级分类Promise对象
      const secondObj = Promise.all(firstObj)
      secondObj.then(result => {
        console.log(result)

        // 等待同时成功后,渲染页面
        const thirdObj = result.map(item => {
          const dataObj = item.data.data
          
          // 这里拼接上一级分类和循环遍历一级分类下的二级分类
          return `
             <div class="item">
        <h3>${dataObj.name}</h3>
        <ul>
          
          ${dataObj.children.map(i => {
            return `
                 <li>
            <a href="javascript:;">
              <img src=${i.picture} />
              <p>${i.name}</p>
            </a>
          </li>
              `
          }).join('')}
         
        </ul>
      </div>
          `
        }).join('')

        document.querySelector('.sub-list').innerHTML = thirdObj
      })
    })

  </script>
</body>

7.案例 - 学习反馈

7.1 完成省市区切换效果

步骤:
  • 1. 设置省份数据到下拉菜单
  • 2. 切换省份,设置城市数据到下拉菜单,并清空地区下拉菜单
  • 3. 切换城市,设置地区数据到下拉菜单

页面展示:

代码:

/**
 * 目标1:完成省市区下拉列表切换
 *  1.1 设置省份下拉菜单数据
 *  1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单
 *  1.3 切换城市,设置地区下拉菜单数据
 */

// 1.1 设置省份下拉菜单数据


axios({
    url: 'http://hmajax.itheima.net/api/province'
}).then(result => {
    // result得到省份对象
    console.log(result)
    const pnameObj = result.data.list.map(pname => {
        return `<option value="${pname}">${pname}</option>`
    }).join('')
    document.querySelector('.province').innerHTML = '<option value="">省份</option>' + pnameObj
})


let pname = ''

// 1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单
document.querySelector('.province').addEventListener('change', e => {
    // 获取到当前对象的value值
    // console.log(e.target.value)
    pname = e.target.value
    axios({
        url: 'http://hmajax.itheima.net/api/city',
        params: { pname }
    }).then(result => {
        // result得到城市的对象
        // console.log(result.data.list)
        const cnameObj = result.data.list.map(cname => {
            return ` <option value="${cname}">${cname}</option>`
        }).join('')
        document.querySelector('.city').innerHTML = ' <option value="">城市</option>' + cnameObj
        // 清空地区下拉菜单
        document.querySelector('.area').innerHTML = '<option value="">地区</option>'
    })
})

// 1.3 切换城市,设置地区下拉菜单数据
document.querySelector('.city').addEventListener('change', e => {
    // 获取到当前对象的value值
    // console.log(e.target.value)

    axios({
        url: 'http://hmajax.itheima.net/api/area',
        params: { pname, cname: e.target.value }
    }).then(result => {
        // result得到地区的对象
        // console.log(result.data.list)
        const anameObj = result.data.list.map(aname => {
            return `<option value="${aname}">${aname}</option>`
        }).join('')
        document.querySelector('.area').innerHTML = '<option value="">地区</option>' + anameObj
    })
})

7.2 收集学习反馈数据,提交保存

步骤:
  • 1. 监听提交按钮的点击事件
  • 2. 依靠插件收集表单数据
  • 3. 基于 axios 提交保存,显示结果

页面展示:

代码:

/**
 * 目标2:收集数据提交保存
 *  2.1 监听提交的点击事件
 *  2.2 依靠插件收集表单数据
 *  2.3 基于axios提交保存,显示结果
 */


// 2.1 监听提交的点击事件
document.querySelector('.submit').addEventListener('click', () => {
    // 2.2 依靠插件收集表单数据
    const form = document.querySelector('.info-form')
    const obj = serialize(form, { hash: true, empty: true })
    // 得到表单的提交数据,该数据为一个对象
    // area: "河东区",city: "天津市"
    console.log(obj)

    // 2.3 基于axios提交保存,显示结果
    axios({
        url: 'http://hmajax.itheima.net/api/feedback',
        method: 'POST',
        data: obj
    }).then(result => {
        console.log(result)
        alert(result.data.message)
    }).catch(error => {
        console.dir(error)
        alert(error.response.data.message)
    })
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2141269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

R语言统计分析——散点图1(常规图)

参考资料&#xff1a;R语言实战【第2版】 R语言中创建散点图的基础函数是plot(x,y)&#xff0c;其中&#xff0c;x和y是数值型向量&#xff0c;代表着图形中的&#xff08;x,y&#xff09;坐标点。 attach(mtcars) plot(wt,mpg,main"Basic Scatter plot of MPG vs. Weigh…

数据结构(Day14)

一、学习内容 结构体 概念 引入&#xff1a;定义整数赋值为10 int a10; 定义小数赋值为3.14 float b3.14; 定义5个整数并赋值 int arr[5] {1 , 2 , 3 , 4 ,5}; 定义一个学生并赋值学号姓名成绩 定义一个雪糕并赋值名称产地单价 问题&#xff1a;没有学生、雪糕 数据类型 解决&…

Text2vec -文本转向量

文章目录 一、关于 Text2vec1、Text2vec 是什么2、Features3、Demo4、News5、Evaluation英文匹配数据集的评测结果&#xff1a;中文匹配数据集的评测结果&#xff1a; 6、Release Models 二、Install三、使用1、文本向量表征1.2 Usage (HuggingFace Transformers)1.3 Usage (se…

★ C++进阶篇 ★ 多态

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C进阶篇第一章----多态 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 C基础篇专栏&#xff1a;★ C基础篇 ★_椎名澄嵐的博客-CSDN博客 …

2024/9/16 英语每日一段

Stark argues that, in their gummies, at least,“The total sugar in a serving is less than in half a cherry.”Of course, cherries also provide fibre, vitamin C, and antioxidants--and 14 of them would count as one of your five-a-day. Artificial sweeteners to…

Ubuntu24.04部署docker

1、更新软件 apt update 2、安装curl apt install apt-transport-https curl 3、导入阿里云GPG秘钥 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg 4、添加Docker阿里云仓库到Ubuntu 24.04的…

使用 release key 对 LineageOS 进行编译和签名

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 为什么需要使用 release key test-key 是一个公开的、众所周知的开发测试密钥&#xff0c;广泛用于测试阶段。这意味着任何人都可以获取这个密钥&#xff0c;…

详解HTTP/HTTPS协议

HTTP HTTP协议全名为超文本传输协议。HTTP协议是应用层协议&#xff0c;其传输层协议采用TCP协议。 请求—响应模型 HTTP协议采用请求-响应模型&#xff0c;通常由客户端发起请求由服务端完成响应。资源存储在服务端&#xff0c;客户端通过请求服务端获取资源。 认识URL 当…

jacoco生成单元测试覆盖率报告

前言 单元测试是日常编写代码中常用的&#xff0c;用于测试业务逻辑的一种方式&#xff0c;单元测试的覆盖率可以用来衡量我们的业务代码经过测试覆盖的比例。 目前市场上开源的单元测试覆盖率的java插件&#xff0c;主要有Emma&#xff0c;Cobertura&#xff0c;Jacoco。具体…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0916)

接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835 接口根路径&#xff1a; http://big-event-vue-api-t.itheima.net 本项目的技术栈 本项目技术栈基于 ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus http:/…

企业社会信任数据,信任指数(2004-2022年)

企业社会信任是指公众对企业及其行为的信任程度&#xff0c;这种信任度是基于企业的商业行为、产品质量、服务态度、信息披露透明度和社会责任履行等多方面因素的综合评估。 2004年&#xff0d;2022年 企业社会信任数据&#xff08;大数据&#xff09;https://download.csdn.n…

【网络】高级IO——select版本TCP服务器

目录 前言 一&#xff0c;select函数 1.1.参数一&#xff1a;nfds 1.2.参数二&#xff1a; readfds, writefds, exceptfds 1.2.1.fd_set类型和相关操作宏 1.2.2.readfds, writefds, exceptfds 1.2.3.怎么理解 readfds, writefds, exceptfds是输入输出型参数 1.3.参数三…

LeetCode[中等] 3. 无重复字符的最长子串

给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 思路&#xff1a;滑动窗口&#xff0c;设置左右指针left与right&#xff0c;maxLength存储长度 利用HashSet性质&#xff0c;存储滑动窗口中的字符 如果没有重复的&#xff0c;那么right继续向…

5.基础漏洞——文件上传漏洞

目录 一.文件上传漏洞原理 二.文件上传漏洞条件&#xff1a; 三.上传限制手段分为两大类 (1)客户端校验 (2)服务端校验 四.具体实现 1.文件上传漏洞——绕过JS检测 2.文件上传漏洞——绕过MIME类型检测 3.文件上传漏洞——绕过黑名单检测 绕过方式:(1) 绕过方式:(2) …

yum本地源配置

yum本地源配置 1.打开虚拟机&#xff0c;点击设置。 2.选择CD/DVD&#xff0c;选择系统镜像文件&#xff0c;设备状态选择“连接”。 3.使用命令lsblk&#xff0c;查看磁盘空间&#xff0c;发现镜像文件。 4.在/dev下找到sr0镜像文件: ls /dev 5.挂载镜像文件&#xf…

闯关leetcode——27. Remove Element

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/remove-element/description/ 内容 Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed. Then retur…

有关C# .NET Core 过滤器的使用

想用一个过滤器实现特定接口的审核日志记录&#xff0c;结果报了错&#xff0c;看了看感觉有些基础要补&#xff0c;所以想记录下来 错误&#xff1a; 在属性过滤器中使用了依赖注入&#xff0c;结果在应用在控制层接口时报了传参的错 //过滤器 public class AuditRecordFil…

C#语言依然是主流的编程语言之一,不容置疑

C#语言是由微软在2000年发布的现代面向对象编程语言。尽管在编程语言市场中的占有率相对较低&#xff0c;但C#依然保持了强大的存在感&#xff0c;并未像一些其他语言那样逐渐被淘汰。C#语言不仅有其存在的独特理由&#xff0c;而且拥有许多令人无法忽视的优势。以下从多个方面…

.Net Gacutil工具(全局程序集缓存工具)使用教程

GAC介绍&#xff1a; GAC&#xff08;Global Assembly Cache&#xff09;全局程序集缓存&#xff0c;是用于存放.Net应用程序共享的程序集。 像平常我们在Visual Studio中引用系统程序集时&#xff0c;这些程序集便来自于GAC。 GAC默认位置为&#xff1a;%windir%\Microsoft…

visual prompt tuning和visual instruction tuning

visual prompt tuning&#xff1a;作为一种微调手段&#xff0c;其目的是节省参数量&#xff0c;训练时需要优化的参数量小。 输入&#xff1a;视觉信息image token可学习的prompt token 处理任务&#xff1a;比如常见的分类任务 visual prompt tuning visual instruction tu…