一、什么是回调函数地狱?
> 在回调函数一直向下嵌套回调函数,形成回调函数地狱
二、回调函数地狱问题?
> 可读性差
> 异常捕获困难
> 耦合性严重
<!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>回调地狱</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>/*** 目标:演示回调函数地狱* 需求:获取默认第一个省,第一个市,第一个地区并展示在下拉菜单中* 概念:在回调函数中嵌套回调函数,一直嵌套下去就形成了回调函数地狱* 缺点:可读性差,异常无法获取,耦合性严重,牵一发动全身*///获取默认第一个省份axios({ url: 'http://ajax-api.itheima.net/api/province' }).then(result => {console.log(result)const pname = result.data.data[0]document.querySelector('.province').innerHTML = pname//获取默认第一个城市axios({ url: 'http://ajax-api.itheima.net/api/city', params: { pname } }).then(result => {console.log(result)const cname = result.data.data[0]document.querySelector('.city').innerHTML = cname//获取默认第一个地区axios({ url: 'http://ajax-api.itheima.net/api/area', params: { pname, cname } }).then(result => {console.log(result)const area = result.data.data[0]document.querySelector('.area').innerHTML = area})})}).catch(error => {console.dir(error)})</script>
</body></html>
三、Promise - 链式调用
概念:依靠 then()方法会返回一个新生成的 Promise 对象特性,继续串联下一环任务,直到结束
细节:then()回调函数中的返回值,会影响新生成的 Promise 对象最终状态和结果
好处:通过Promise链式调用,解决回调函数嵌套问题
总结:
1.什么是 Promise 的链式调用?
> 使用 then 方法返回新 Promise 对象特性,一直串联下去
2.then 回调函数中,return 的值会传给哪里?
> 传给 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><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 new Promise((resolve, reject) => {setTimeout(() => {resolve(result + '----邢台')}, 2000)})})//4.获取城市名字const p3 = p2.then(result => {console.log(result)//创建Promise,模拟请求地区名字return new Promise((resolve, reject) => {setTimeout(() => {console.log(result + '---信都区')}, 2000)})})//获取地区名字p3.then(result => {console.log(result)})//then()原地的结果是一个新的Promise对象console.log(p2 === p);</script>
</body></html>
四、Promise - 链式调用应用(解决回调函数地狱问题)
目标:使用 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 = ''//获取省份Promise对象axios({ url: 'http://ajax-api.itheima.net/api/province' }).then(result => {// console.log(result)pname = result.data.data[0]document.querySelector('.province').innerHTML = pname//获取城市Promise对象return axios({ url: 'http://ajax-api.itheima.net/api/city', params: { pname } })}).then(result => {console.log(result)const cname = result.data.data[0]document.querySelector('.city').innerHTML = cname//获取地区Promise对象return axios({ url: 'http://ajax-api.itheima.net/api/area', params: { pname, cname } })}).then(result => {console.log(result)const area = result.data.data[0]document.querySelector('.area').innerHTML = area})</script>
</body></html>
五、async函数和await
定义:
async 函数是使用 async 关键字声明的函数。async 函数是 asyncFunction 构造函数的实例,并且其中允许使用 await 关键字。async 和 await 关键字让我们可以用一种更简洁的方式写出基于 promise 的异步行为,而无需刻意地链式调用 promise。
概念:
在 async 函数内,使用 await 关键字取代 then 函数,等待获取 Promise 对象成功状态的结果值
async函数和await_捕获错误:
使用:try...catch 语句标记要尝试的语句块,并指定一个出现异常时抛出的响应。
语法:
六、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会阻止"异步函数内"代码继续执行,原地等待结果)*/async function getData() {try {//try包裹可能产生错误的代码const pObj = await axios({ url: 'http://ajax-api.itheima.net/api/province' })const pname = pObj.data.data[0]const cObj = await axios({ url: 'http://ajax-api.itheima.net/api/city', params: { pname } })const cname = cObj.data.data[0]const aObj = await axios({ url: 'http://ajax-api.itheima.net/api/area', params: { pname, cname } })const area = aObj.data.data[0]document.querySelector('.province').innerHTML = pnamedocument.querySelector('.city').innerHTML = cnamedocument.querySelector('.area').innerHTML = area} catch (error) {//catch接受错误信息//如果try中某行代码报错后,try中剩余的代码不会执行了console.dir(error)}}getData()</script>
</body></html>