同步代码和异步代码?
同步代码: 逐行执行, 需原地等待结果后,才继续向下执行.
异步代码: 调用后耗时, 不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数.
JS中异步代码:
setTimeout/ setInterval
事件
AJAX
异步代码依靠回调函数来接受结果.
回调函数地狱: 在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱.
缺点: 可读性差,异常无法获取,耦合性严重,牵一发动全身.
---
如何解决回调函数地狱问题?
Promise - 链式调用: 依靠then()方法会返回一个新生成的Promise对象特性,继续串联下一环任务,直到结束.
then回调函数中,return的值会传到哪里?
答: 传给then函数生成的新Promise对象
//1. 生成一个Promise对象 const p = new Promise((resolve, reject) => { setTimeout(() => { resolve('四川省') }, 2000) }) //2. 获取省份名字 const p2 = p.then(result => { console.log(result) //return Promise对象最终状态和结果,影响到新的Promise对象 return new Promise(resolve, reject) => { setTimeout(() => { resolve(result + '---成都') }, 2000) }) }) //3. 获取城市名字 p2.then(result => { console.log(result) })
async函数和await:
在async函数内,使用await关键字取代then函数,等待获取Promise对象成功状态的结果值.
错误捕获: try ... catch
try{
// 要执行的代码
}catch(error){
//error接收的是,错误信息
//try里代码,若有错误,直接进入这里执行
}
事件循环:EventLoop
事件循环负责执行代码,收集和处理事件以及执行队列中的子任务.
定义: 执行代码和收集异步任务的模型, 在调用栈空闲,反复调用任务队列里回调函数的执行机制.
为什么存在事件循环:
答: JS是单线程的,为了不阻塞JS引擎,设计执行代码的模型.
JS内代码如何执行?
答: 1. 执行同步代码,遇到异步代码交给宿主浏览器环境执行
2. 异步有了结果,把回调函数放入任务队列中排队
3. 当调用栈空闲后,反复调用任务队列里的回调函数
宏任务与微任务:
宏任务: 由浏览器环境执行的异步代码, JS脚本执行事件,setTimeout/setInterval,AJAX请求完成事件,用户交互事件.
微任务: 由JS引擎环境执行的异步代码, Promise对象.then()的回调
注意: Promise本身是同步的,而then和catch回调函数是异步的
同时存在宏任务队列和微任务队列,优先执行微任务队列
Promise.all静态方法:
合并多个Promise对象,等待所有同时成功完成(或某一个失败),做后续逻辑.
语法:
const p = Promise.all([Promise对象, Promise对象, ...])
p.then(result => {
//result结果: [Promise对象成功结果, Promise对象成功结果, ...]
}).catch(error => {
//第一个失败的Promise对象,抛出的异常
})