一:什么是回调函数地狱
在一个回调函数中嵌套另一个回调函数(甚至一直嵌套下去),形成回调函数地狱
回调函数地狱存在问题:
- 可读性差
- 异常捕获严重
- 耦合性严重
// 1. 获取默认第一个省份的名字
axios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {
const pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
// 2. 获取默认第一个城市的名字
axios({url: 'http://hmajax.itheima.net/api/city', params: { pname }}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
// 3. 获取默认第一个地区的名字
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
})
})
}).catch(error => {
console.dir(error)
})
每一axios函数then方法的回调函数中嵌套着其他回调函数,导致可读性非常差。如果内部axios函数有错误,通过catch也难以捕获错误信息。
二:Promise——链式调用
什么是链式调用
- Promise对象.then(result=>{return new Promise()})方法会返回一个新生成的Promise对象
- 在其then方法的回调函数中return返回值,会影响Promise对象.then所生成的Promise对象最终状态和结果。
- 利用Promise.then生成的新的Promise对象的then方法,接收return返回值
- 依据不停的Promise链式调用,最终实现任务达成
一句话,使用then方法返回新的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对象(p.then生成的Promise对象)
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + '---北京')
}, 2000)
})
})
p2.then(result => {
console.log(result);//北京市---北京
})
console.log(p2);//Promise对象
下面就是利用链式调用,实现查找省份、城市下,市区名字查找
<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>
作用
Promise链式调用解决了回调函数地狱问题