AJAX 进阶 day4

目录

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 = pnamedocument.querySelector('.city').innerHTML = cnamedocument.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 = pnamedocument.querySelector('.city').innerHTML = cnamedocument.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.valueaxios({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.xdnf.cn/news/142413.html

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

相关文章

【有啥问啥】对比学习(Contrastive Learning,CL)的原理与前沿应用详解

对比学习&#xff08;Contrastive Learning&#xff0c;CL&#xff09;的原理与前沿应用详解 对比学习&#xff08;Contrastive Learning&#xff09;是自监督学习领域的关键方法之一&#xff0c;近年来因其在图像、文本和跨模态任务上的优越表现&#xff0c;受到了学术界和工…

【重学 MySQL】三十、数值类型的函数

【重学 MySQL】三十、数值类型的函数 基本函数角度与弧度互换函数三角函数指数与对数进制间的转换示例 基本函数 MySQL提供了一系列基本的数值函数&#xff0c;用于处理数学运算和数值转换。以下是一些常用的基本函数及其用法&#xff1a; 函数用法ABS(x)返回x的绝对值。SIGN…

Linux下文件下载中文乱码问题

最近做的一个项目中&#xff0c;本地打包到线上后&#xff0c;发现生成的文件中出现中文乱码&#xff0c;但在本地运行正常。经排查&#xff0c;文件输入输出流都指定了utf-8的编码格式&#xff0c;IDE的File Encodings也都是utf-8&#xff0c;Linux编码格式也是utf-8&#xff…

商务人士必备的精准翻译工具盘点

网易翻译是一款我外出游玩时候必备的翻译工具&#xff0c;最近没出去玩但是有更多的翻译需求了&#xff0c;为了方便在电脑上的操作我也找了不少翻译工具&#xff0c;这次一起分享给大家&#xff0c;看看哪款更得你的眼缘。 1.福昕在线翻译 链接直达&#xff1a;https://fany…

回归预测|基于灰狼优化正则化极限学习机的数据回归预测Matlab程序GWO-RELM 多特征输入单输出

回归预测|基于灰狼优化正则化极限学习机的数据回归预测Matlab程序GWO-RELM 多特征输入单输出 文章目录 一、基本原理1. 极限学习机&#xff08;ELM&#xff09;模型2. 灰狼优化算法&#xff08;GWO&#xff09;3. GWO-RELM回归预测流程总结 二、实验结果三、核心代码四、代码获…

C++——多线程编程(从入门到放弃)

进程&#xff1a;运行中的程序 线程&#xff1a;进程中的进程 线程的最大数量取决于CPU的核心数 一、将两个函数添加到不同线程中 demo&#xff1a;两个函数test01()和test02()&#xff0c;实现将用户输入的参数进行打印输出1000次 将这两个函数均放到独立的线程t1和t2中&…

【优化器】Optimizer——深度学习中的优化器是什么作用呢?

【优化器】Optimizer——深度学习中的优化器是什么作用呢&#xff1f; 【优化器】Optimizer——深度学习中的优化器是什么作用呢&#xff1f; 文章目录 【优化器】Optimizer——深度学习中的优化器是什么作用呢&#xff1f;1.什么是优化器&#xff1f;梯度下降法3. 常见的优化…

在typescript浏览器端中调用C++编写的函数,WebAssembly传递指针类型的参数,以及处理指针类型的返回值。

首先要在Cmake工程中的cmakelists.txt文件中引入Emscripten工具链&#xff1a; set(CMAKE_TOOLCHAIN_FILE "D:/CppPkg/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake")直接看C代码&#xff1a; #include <emscripten/emscripten.h> #i…

鸿蒙开发之ArkTS 基础六 对象

什么是对象的呢&#xff1f;就是描述物体的特征和行为&#xff0c;是可以存储多种数据的容器 对象的定义和使用 let 对象名称: 对象结构类型 值 通过interface 关键字来约定对象结构类型,语法结构如下&#xff1a; interface 对象名{ 属性1&#xff1a;类型 属性2&#…

11.01类的定义和对象的使用(练习)

类的定义 类名&#xff1a;手机(Phone) 成员变量&#xff1a;品牌(brand&#xff09;&#xff0c;价格&#xff08;price&#xff09; 成员方法&#xff1a;打电话(calL)&#xff0c;发短信&#xff08;sendMessage&#xff09; 调用类变量和方法

基于SpringBoot+Vue+MySQL的高校心理教育辅导系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着社会的快速发展&#xff0c;大学生群体面临着日益复杂的学习、生活及就业压力&#xff0c;心理健康问题日益凸显。传统的面对面心理咨询方式因时间、空间等限制&#xff0c;难以满足学生多样化的需求。因此&#xff0c;利用…

基于spring的ssm整合

目录 基于spring的ssm整合 Spring 框架 SpringMVC 框架 MyBatis 框架 1.创建项目 2.导入依赖 3.导入sql 4.创建jdbc.propries文件 1&#xff09;mysql8以下 2&#xff09;mysql8以上的 5.创建mybatis-config.xml配置文件 6.创建spring-Config.xml文件 7.创建项目所需包和类 1&a…

2024-1.2.12-Android-Studio配置

本地博客: https://k1t0111.github.io/ K1T0 最近在做一些app方向的移动技术开发学习&#xff0c;但是由于AS的配置问题&#xff0c;市面上找不到最新的2024版本的AS的相关配置。笔者也是踩了很多坑&#xff0c;因此想写一篇文章记录一下最新的AS 2024 1.2.12的对应java环境的一…

Html css样式总结

1.Html css样式总结 1.1. 定位position 布局是html中非常重要的一部分&#xff0c;而定位在页面布局中也是使用频率很高的方法&#xff0c;本章节为定位在布局中的使用技巧和注意事项。   position定位有4个属性&#xff0c;分别是static(默认&#xff09;&#xff0c;absol…

CLIP论文中关键信息记录

由于clip论文过长&#xff0c;一直无法完整的阅读该论文&#xff0c;故而抽取论文中的关键信息进行记录。主要记录clip是如何实现的的&#xff08;提出背景、训练数据、设计模式、训练超参数、prompt的作用&#xff09;&#xff0c;clip的能力&#xff08;clip的模型版本、clip…

感知器神经网络

1、原理 感知器是一种前馈人工神经网络&#xff0c;是人工神经网络中的一种典型结构。感知器具有分层结构&#xff0c;信息从输入层进入网络&#xff0c;逐层向前传递至输出层。根据感知器神经元变换函数、隐层数以及权值调整规则的不同&#xff0c;可以形成具有各种功能特点的…

学习笔记 韩顺平 零基础30天学会Java(2024.9.15)

P557 泛型应用实例 P558 泛型使用细节1 P560 泛型使用细节2 P560 泛型课堂练习 代码见Exceise P561 自定义泛型类 对于第二点&#xff0c;因为不知道类型&#xff0c;所以不知道开辟多少空间&#xff0c;因此不能初始化 第三点&#xff0c;静态方法与类相关的&#xff0c;在类…

LeetCode[中等] 189.轮转数组

给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 思路 创建一个新数组&#xff0c;存储原数组旋转后的元素&#xff0c;然后将新数组中的元素复制回原数组。 public class Solution {public void Rotate(int[] nums, int k)…

【docker】阿里云使用docker,2024各种采坑

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ dial tcp: lookup on 8.8.8.8:53: no such host失败属于DNS问题 2️⃣ docker镜像配置配置最新镜像源 3️⃣ 【重点】阿里云专用获取自己的镜像加速器地址配置镜像地址 &#x1f6ec; 文章小结&#x1f4d6; 参考资料 &#x…

一款强大的吉他乐谱编辑软件GuitarPro 8.2中文解锁版

GuitarPro 8.2中文解锁版是一款强大的吉他乐谱编辑软件&#xff0c;适合新手和专业乐手。它提供详尽教程和实用工具&#xff0c;助力初学者掌握吉他技巧&#xff1b;对于专业乐手&#xff0c;它精准记录音符和节奏&#xff0c;提供丰富编辑功能和音效处理。此外&#xff0c;软件…