什么叫回调地狱
简单来说–在回调函数内, 再嵌套回调函数, 一直嵌套下去形成了回调地狱
体验回调地狱
// 目标: 获取所有省市区数据, 随便获取
// 1. 获取所有省份列表
axios.get('http://.....').then(res => {
// 2. 获取某个省, 对应的城市列表
let pname = res.data.data[5];
axios.get('http://.....').then(res => {
// 3. 获取某个市, 对应的地区列表
let cname = res.data.data[0]
axios.get('http://.....').then(res => {
console.log(res);
})
})
})
要想知道如何解决回调地狱,就要先了解回调函数
回调函数
当一个函数被当做另一个函数的参数的时候,这个函数就叫做回调函数.简单来说就是一个函数定义了,但是没有立即去调用它,而是交给了另一个函数去调用,这就叫做回调函数
回调函数的优点—实现业务逻辑和操作分离开来,单独修改操作,不影响业务逻辑,方便操作
回调函数的缺点—传统的回调函数去解决异步操作,无法避免大量使用回调函数嵌套,形成回调地狱
传统的回调函数去解决异步操作会出现回调地狱的缺点,因此我们可以通过优化回调地狱来解决这一问题
1.Promise
Promise是一个ES6提出一个新语法,用来优化异步代码的写法。(详细的Promise用法看我上篇文章)
因为Promise的.then()的返回值是一个新的Promise对象,因此可以用Promise的链式调用来优化回调地狱
用Promise优化上面代码
原理—根据.then的链式调用把Promise对象串联起来
// 目标: 使用Promise的链式调用解决问题
// 前提: axios函数在原地返回的就是一个Promise对象
axios.get('http:....').then(res => {
// 2. 获取某个省, 对应的城市列表
let pname = res.data.data[5];
return axios.get('http:....')
}).then(res => {
// 3. 获取某个市, 对应的地区列表
let cname = res.data.data[0]
return axios.get('http:....')
}).then(res => {
console.log(res);
})
Promise的缺点
- 无法取消Promise,一旦新建他就会立即执行,无法中途取消
- 如果不设置回调函数,Promise内部抛出错误,不会反应到外部
- 当处于pending状态的时候,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
2.async await
ES7提供了async函数,使得异步操作变得更加方便
语法
async function 函数名() {
const result = await Promise对象
// 拿到Promise对象内成功的结果继续向下执行
}
注意!!
- await 必须用在async修饰的函数内
- 一个函数如果加上了 async name这个函数的返回值就会变成一个Promise对象,该函数也会变成一个异步函数
用async await优化上面代码
// 目标: 使用Promise的链式调用解决问题
// 前提: axios函数在原地返回的就是一个Promise对象
async function f() {
const provinces = await axios.get('http://....')
const pname = provinces.data.data[5]
const citys = await axios.get('http://....')
const cname = citys.data.data[0]
const areas = await axios.get('http://....')
return areas
}
f()
await后面一般跟Promise对象
- 如果跟的是非Promise对象, 则等待所有同步代码执行后, 把此结果作为成功的结果留在原地使用
- 如果是Promise对象, 则等待Promise对象内触发resolve返回成功结果, 在原地使用
await不能捕获失败结果, 需要使用try+catch关键字捕获
语法
try {
// 这里放可能在执行中报错的代码
// 如果报错会终止代码继续执行, 直接跳转进catch里执行
} catch (err) {
// err接收try大括号内报错抛出的异常代码
}
let p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve(1)
reject(new Error('失败'))
}, 2000)
})
async function myFn() {
try {
const res = await p
console.log(res);
} catch (err) {
console.error(err)
}
}
myFn()
说的不是很好 欢迎大家指正其中可能存在的错误和问题 谢谢大家