解决回调函数地狱问题

回调函数地狱

  1. 再回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱
  2. 缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身

如下列代码:

<script>
	axios({ url: 'http://hmajax.itheima.net/api/province' }).then(result => {
	  const pname = result.data.list[0]
	  document.querySelector('.province').innerHTML = pname
	  // 获取第一个省份默认下属的第一个城市名字
	  axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname } }).then(result => {
	    const cname = result.data.list[0]
	    document.querySelector('.city').innerHTML = cname
	    // 获取第一个城市默认下属第一个地区名字
	    axios({ url: 'http://hmajax.itheima.net/api/area', params: { pname, cname } }).then(result => {
	      document.querySelector('.area').innerHTML = result.data.list[0]
	    })
	  })
	})
script>

Promise - 链式调用

  1. 概念:依靠 then() 方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束
  2. 细节:then() 回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果
  3. 好处:通过链式调用,解决回调函数嵌套问题
    解决回调函数地狱问题_第1张图片
  4. 按照图解,编写核心代码:
<script>
	/**
	 * 目标:掌握Promise的链式调用
	 * 需求:把省市的嵌套结构,改成链式调用的线性结构
	*/
	// 1. 创建Promise对象-模拟请求省份名字
	const p = new Promise((resolve, reject) => {
	  setTimeout(() => {
	    resolve('北京市')
	  }, 2000)
	})
	
	// 2. 获取省份名字
	const p2 = p.then(result => {
	  console.log(result)
	  // 3. 创建Promise对象-模拟请求城市名字
	  // return Promise对象最终状态和结果,影响到新的Promise对象
	  return new Promise((resolve, reject) => {
	    setTimeout(() => {
	      resolve(result + '--- 北京')
	    }, 2000)
	  })
	})
	
	// 4. 获取城市名字
	p2.then(result => {
	  console.log(result)
	})
	
	// then()原地的结果是一个新的Promise对象
	console.log(p2 === p) // false
script>

## Promise-链式调用_解决回调地狱

  1. 做法:每个 Promise 对象中管理一个异步任务,用 then 返回 Promise 对象,串联起来
    解决回调函数地狱问题_第2张图片
  2. 按照图解思路,编写核心代码:
<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>

async 函数和 await

  1. 概念:再 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值
  2. 做法:使用 async 和 await 解决回调地狱问题
  3. 核心代码:
<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>

async 函数和 await 捕获错误

  1. try 和 catch 的作用:语句标记要尝试的语句块,并指定一个出现异常时抛出的响应
<script>
	try {
	  // 要执行的代码
	} catch (error) {
	  // error 接收的是,错误消息
	  // try 里代码,如果有错误,直接进入这里执行
	}
script>

try 里有报错的代码,会立即跳转到 catch 中
2. 尝试把代码中 url 地址写错,运行观察 try catch 的捕获错误信息能力

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

你可能感兴趣的:(javascript,前端)