什么叫回调地狱

简单来说–在回调函数内, 再嵌套回调函数, 一直嵌套下去形成了回调地狱

axios终止回调 axios解决回调地狱_回调函数

体验回调地狱
// 目标: 获取所有省市区数据, 随便获取
// 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()

说的不是很好 欢迎大家指正其中可能存在的错误和问题 谢谢大家