目录
同步代码和异步代码
回调函数地狱
Promise - 链式调用
async函数和await
async函数和await_捕获错误
事件循环-EventLoop
宏任务与微任务
Promise.all 静态方法
同步代码和异步代码
同步代码:
逐行
执行,需
原地等待
结果
后,才继续向下执行
异步代码:调用后
耗时
,不阻塞代码继续执行(不必原地等待),在
将来
完成后触发一个
回调函数
1. 什么是同步代码?➢ 逐行执行, 原地等待 结果 后,才继续向下执行2. 什么是异步代码?➢ 调用后 耗时 ,不阻塞代码执行,将来完成后触发 回调函数3. JS 中有哪些异步代码?➢ setTimeout / setInterval➢ 事件➢ AJAX4. 异步代码如何接收结果?➢ 依靠 回调函数 来接收
回调函数地狱
概念:在回调函数中
嵌套回调函数
,一直嵌套下去就形成了
回调函数地狱
缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身
Promise - 链式调用
概念:依靠 then() 方法会返回一个
新生成的 Promise 对象
特性,继续串联下一环任务,直到结束
细节:then() 回调函数中的
返回值
,会影响新生成的 Promise 对象
最终状态和结果
好处:通过链式调用,解决回调函数嵌套问题
let pname = ''
axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
return axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } })
}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
return axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
}).then(result => {
const area = (result.data.list[0])
document.querySelector('.area').innerHTML = area
})
async函数和await
概念: 在 async 函数内,使用 await 关键字取代 then 函数,
等待
获取 Promise 对象
成功状态的结果值
注意:await必须用在async修饰的函数内(await会阻止"异步函数内"代码继续执行,原地等待结果)
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 areaObj = await axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } })
const area = areaObj.data.list[0]
document.querySelector('.province').innerHTML = pname
document.querySelector('.city').innerHTML = cname
document.querySelector('.area').innerHTML = area
}
getData()
async函数和await_捕获错误
try包裹可能产生错误的代码
如果try里某行代码报错后,try中剩余的代码不会执行了
事件循环-EventLoop
原因:JavaScript 单线程(某一刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了
事件循环模型
定义:执行代码和收集异步任务的模型,在调用栈空闲,反复调用任务队列里回调函数的执行机制,就叫事件循环
1. 什么是事件循环?➢ 执行代码 和收集异步任务,在调用栈空闲时,反复调用任务队列里回调函数执行机制2. 为什么有事件循环?➢ JavaScript 是单线程的,为了 不阻塞 JS 引擎 ,设计执行代码的模型3. JavaScript 内代码如何执行?➢ 执行同步代码,遇到 异步代码 交给 宿主 浏览器环境执行➢ 异步有了结果后,把回调函数放入 任务队列排队➢ 当调用栈 空闲 后,反复调用任务队列里的回调函数
宏任务与微任务
ES6 之后引入了 Promise 对象, 让 JS 引擎也可以发起异步任务
异步任务分为:
✓
宏任务
:由
浏览器
环境执行的异步代码
✓
微任务
:由
JS 引擎
环境执行的异步代码
JavaScript 内代码如何执行?
➢
执行第一个 script 脚本事件宏任务,里面
同步
代码
➢
遇到
宏任务/微任务
交给宿主环境,有结果回调函数进入对应队列
➢
当执行栈空闲时,
清空微任务
队列,再执行
下一个宏任务
,从1再来
自己理解:当执行栈空闲时,优先执行
微任务
队列,因为
微任务是
由
JS 引擎
环境执行的异步代码
Promise.all 静态方法
概念:合并多个 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' } })
const p = Promise.all([bjPromise, shPromise, gzPromise, szPromise])
// console.log(p);
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('ul').innerHTML = htmlStr
}).catch(error => {
console.dir(error)
})