(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)
目录
同步代码和异步代码
回调函数地狱
Promise - 链式调用
Promise 链式应用
async函数和await
async函数和await_捕获错误
事件循环-EventLoop
认识 - 事件循环(EventLoop)
事件循环 - 执行过程
总结
宏任务与微任务
宏任务与微任务 - 执行顺序
同步代码和异步代码
同步代码:
异步代码:
同步代码: 逐行 执行,需 原地等待 结果 后,才继续向下执行异步代码:调用后 耗时 ,不阻塞代码继续执行(不必原地等待),在 将来 完成后触发一个 回调函数
回调函数地狱
需求:展示默认第一个省,第一个城市,第一个地区在下拉菜单中概念:在回调函数中 嵌套回调函数 ,一直嵌套下去就形成了回调函数地狱缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身
<body><form><span>省份:</span><select><option class="province"></option></select><span>城市:</span><select><option class="city"></option></select><span>地区:</span><select><option class="area"></option></select></form><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:演示回调函数地狱* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中* 概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱* 缺点:可读性差,异常无法获取,耦合性严重,牵一发动全身*/// 1. 获取默认第一个省份的名字axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {const pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2. 获取默认第一个城市的名字axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }}).then(result => {const cname = result.data.list[0]document.querySelector('.city').innerHTML = cname// 3. 获取默认第一个地区的名字axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }}).then(result => {console.log(result)const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})})}).catch(error => {console.dir(error)})</script>
</body>
Promise - 链式调用
概念:依靠 then() 方法会返回一个 新生成的 Promise 对象 特性,继续串联下一环任务,直到结束细节:then() 回调函数中的 返回值 ,会影响新生成的 Promise 对象 最终状态和结果好处:通过链式调用,解决回调函数嵌套问题
<body><script>/*** 目标:掌握Promise的链式调用* 需求:把省市的嵌套结构,改成链式调用的线性结构*/// 1. 创建Promise对象-模拟请求省份名字const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('北京市')}, 2000)})// 2. 获取省份名字const p2 = p.then(result => {console.log(result)// 3. 创建Promise对象-模拟请求城市名字// return Promise对象最终状态和结果,影响到新的Promise对象return new Promise((resolve, reject) => {setTimeout(() => {resolve(result + '--- 北京')}, 2000)})})// 4. 获取城市名字p2.then(result => {console.log(result)})// then()原地的结果是一个新的Promise对象console.log(p2 === p)</script>
</body>
Promise 链式应用
目标:使用 Promise 链式调用,解决回调函数地狱问题
做法:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来
<body><form><span>省份:</span><select><option class="province"></option></select><span>城市:</span><select><option class="city"></option></select><span>地区:</span><select><option class="area"></option></select></form><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:把回调函数嵌套代码,改成Promise链式调用结构* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中*/let pname = ''// 1. 得到-获取省份Promise对象axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {pname = result.data.list[0]document.querySelector('.province').innerHTML = pname// 2. 得到-获取城市Promise对象return axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }})}).then(result => {const cname = result.data.list[0]document.querySelector('.city').innerHTML = cname// 3. 得到-获取地区Promise对象return axios({url: 'http://hmajax.itheima.net/api/area', params: { pname, cname }})}).then(result => {console.log(result)const areaName = result.data.list[0]document.querySelector('.area').innerHTML = areaName})</script>
</body>
async函数和await
定义:
概念: 在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值
<body><form><span>省份:</span><select><option class="province"></option></select><span>城市:</span><select><option class="city"></option></select><span>地区:</span><select><option class="area"></option></select></form><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 目标:掌握async和await语法,解决回调函数地狱* 概念:在async函数内,使用await关键字,获取Promise对象"成功状态"结果值* 注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)*/// 1. 定义async修饰函数async function getData() {// 2. await等待Promise对象成功的结果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('.province').innerHTML = pnamedocument.querySelector('.city').innerHTML = cnamedocument.querySelector('.area').innerHTML = areaName}getData()</script>
</body>
async函数和await_捕获错误
使用:
语法:
事件循环-EventLoop
认识 - 事件循环(EventLoop)
概念:
原因:JavaScript 单线程(某一刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环模型
事件循环 - 执行过程
定义:执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环
总结
1. 什么是事件循环?执行代码 和收集异步任务,在调用栈空闲时,反复调用任务队列里回调函数执行机制2. 为什么有事件循环?JavaScript 是单线程的,为了 不阻塞 JS 引擎 ,设计执行代码的模型3. JavaScript 内代码如何执行?执行同步代码,遇到 异步代码 交给 宿主 浏览器环境执行异步有了结果后,把回调函数放入 任务队列排队当调用栈 空闲 后,反复调用任务队列里的回调函数
宏任务与微任务
ES6 之后引入了 Promise 对象, 让 JS 引擎也可以发起异步任务异步任务分为:宏任务 :由 浏览器 环境执行的异步代码微任务 :由 JS 引擎 环境执行的异步代码Promise 本身是同步的,而then和catch回调函数是异步的