一、同步代码和异步代码
1.同步代码
浏览器是按照我们书写代码的顺序一行一行地执行程序的。浏览器会等待代码的解析和工作,在上一行完成之后才会执行下一行。这也使得它成为一个同步程序。
总结来说:逐行执行,需原地等待结果后,才继续向下执行
2.异步代码
异步编程技术使你的程序可以在一个可能长期运行的任务的同时继续对其他事件做出反应而不必等待任务完成。与此同时,你的程序也将在任务完成后显示结果。
总结来说:调用后耗时,不阻塞代码继续执行(不必原地等待),在将来完成后触发一个回调函数
3.JS中有哪些异步代码
setTimeout/setinterval
事件
AJAX
4.异步代码如何接收结果
依靠回调函数来接收
5.示例
1作为同步代码,立即执行,往下是3,是一个异步代码,先放一边,4也是一个异步代码,也放一边,2是一个同步代码,立即执行,然后等两秒一过,3开始执行,4是点击才执行
二、回调函数地狱
1.回调函数地狱代码演示
<!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: 'https://hmajax.itheima.net/api/province' }).then(result => {
console.log(result)
const pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
//2获取默认第一个城市的名字
axios({ url: 'https://hmajax.itheima.net/api/city', params: { pname } }).then(result => {
console.log(result)
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
//3获取默认第一个地区的名字
axios({ url: 'https://hmajax.itheima.net/api/area', params: { pname, cname } }).then(result => {
const areaName = result.data.list[0]
document.querySelector('.area').innerHTML = areaName
})
})
})
</script>
</body>
</html>
2.概念及缺点
通过上面例子我们不难发现,回调函数中嵌套着回调函数一直嵌套着下去就形成了回调函数地狱
缺点:可读性差,异常无法捕获,耦合性严重,牵一发动全身
三、解决回调函数地狱问题
1.Promise-链式调用
(1)概念
依靠then()方法返回一个新生成的Promise对象特性,继续串联下一环任务,直到结束
细节:then()回调函数中的返回值,会影响新生成的Promise对象最终状态和结果
好处:通过链式调用,解决回调函数嵌套问题
(2)模拟代码
<!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 Promise对象最终状态和结果,影响到新的Promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result + '---北京')
}, 2000);
})
})
//获取城市名字
p2.then(result => {
console.log(result)
})
</script>
</body>
</html>
(3)实际案列代码
<!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 得到省份的Promsi对象
axios({ url: 'https://hmajax.itheima.net/api/province' }).then(result => {
pname = result.data.list[0]
document.querySelector('.province').innerHTML = pname
//2 获取城市
return axios({ url: 'https://hmajax.itheima.net/api/city', params: { pname } })
}).then(result => {
const cname = result.data.list[0]
document.querySelector('.city').innerHTML = cname
//3.获取地区
return axios({ url: 'https://hmajax.itheima.net/api/area', params: { pname, cname } })
}).then(result => {
const areaName = result.data.list[0]
document.querySelector('.area').innerHTML = areaName
})
</script>
</body>
</html>
2.async函数和await
(1) 定义
async函数是使用async关键字声明的函数。async函数是AsyncFunction构造函数的实例,并且其中运行使用await关键字。async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise.
(2)概念
在async函数内,使用await关键字取代then函数,等待获取Promise对象成功状态的结果值
(3)代码示例
<!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: 'https://hmajax.itheima.net/api/province' })
const pname = pObj.data.list[0]
const cObj = await axios({ url: 'https://hmajax.itheima.net/api/city', params: { pname } })
const cname = cObj.data.list[0]
const aObj = await axios({ url: 'https://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>
(4)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]
//我们将获取地区的资源路径写错多写一个1
const aObj = await axios({ url: 'http://hmajax.itheima.net/api/area1', 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>