如何解决“回调函数地狱”

72 阅读4分钟

目录

1. “Promise 链式调用”和“async 和 await 使用”

1.1. Promise 链式调用介绍

1.1.1. 概念

1.1.2. 细节

1.1.3. 目的

1.1.4. Promise 链式应用-解决展示默认第一个省,第一个城市,第一个地区在下拉菜单中的回调函数地狱问题

1.2. async 和 await 使用介绍

1.2.1. 定义

1.2.2. 概念

1.2.3. 示例

1.2.4. async函数和await如何捕获错误?

1.2.4.1. 使用

1.2.4.2. 语法

1.2.5. async函数和await应用-解决展示默认第一个省,第一个城市,第一个地区在下拉菜单中的回调函数地狱问题

1.2.6. async函数和await捕获错误应用


 

1. “Promise 链式调用”和“async 和 await 使用”


 

1.1. Promise 链式调用介绍

1.1.1. 概念

  • 依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束

1.1.2. 细节

  • then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果

1.1.3. 目的

  • 使用 Promise 链式调用,解决回调函数嵌套问题(回调函数地狱问题)

1.1.4. Promise 链式应用-解决展示默认第一个省,第一个城市,第一个地区在下拉菜单中的回调函数地狱问题

  • 做法:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Promise链式调用_解决回调地狱</title>
</head>

<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>

</html>


 

1.2. async 和 await 使用介绍

1.2.1. 定义

  • async函数是使用async关键字声明的函数。async函数是AsyncFunction构造函数的实例,并且其中允许使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。

1.2.2. 概念

  • 在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值

1.2.3. 示例

1.2.4. async函数和await如何捕获错误?

1.2.4.1. 使用

1.2.4.2. 语法

1.2.5. async函数和await应用-解决展示默认第一个省,第一个城市,第一个地区在下拉菜单中的回调函数地狱问题

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>async函数和await_解决回调函数地狱</title>
</head>

<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 = pname
      document.querySelector('.city').innerHTML = cname
      document.querySelector('.area').innerHTML = areaName
    }

    getData()
  </script>
</body>

</html>

1.2.6. async函数和await捕获错误应用

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>async函数和await_错误捕获</title>
</head>

<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 function getData() {
      // 1. try包裹可能产生错误的代码
      try {
        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 = pname
        document.querySelector('.city').innerHTML = cname
        document.querySelector('.area').innerHTML = areaName
      } catch (error) {
        // 2. 接着调用catch块,接收错误信息
        // 如果try里某行代码报错后,try中剩余的代码不会执行了
        console.dir(error)
      }
    }

    getData()
  </script>
</body>

</html>