一、了解回调地狱问题
在说回调地狱之前我们首先得要了解到什么是回调地狱。我们来看一段代码,如下图所示(其中还有接口等等文件就不一一举出了,只针对回调地狱问题说明)
大家先看这段代码是可以连续发三个请求,并且按顺序执行,第一个请求拿到的数据再往下走,再去拿数据,最后一环套一环,也可以理解为嵌套请求,这样写就跟套娃一样,如果一直写下去那么就会越来越夸张,阅读性就非常差,更不方便后期维护。这种写法就叫
‘回调地狱’
二、如何去避免和解决回调地狱?
解决方法一: Promise
Promise 是承诺的意思,es6中提出的一个新api
作用:用来优化异步代码,可以替换掉传统函数回调的解决方案。
解决如下:
getDataPromise('http://localhost:3000/get').then(res => {
return getDataPromise('http://localhost:3000/getCategory?id=' + res[0].id)
}).then(res => {
return getDataPromise('http://localhost:3000/getNews?id=' + res[0].id)
}).then(res => {
console.log('成功', res)
})
下面对代码进行拆分解析如图所示:
这样看起来代码会更好维护和优化,看起来也非常醒目。不会像之前那样无限套。
解决方法二: async/await语法
async,await是es7中新增的语法,用来进一步改进一步代码的写法,是promise升级版.
async:
async 函数返回一个Promise 对象
async 函数内部return语句返回的值是Promise对象的值
await 命令
await 的外层函数必须有一个async
正常情况下,await,命令后面是一Promise对象,返回该promise的值。如果不是Promise对象,就直接返回对应的值。
async函数内部的执行流程
在执行async函数(设名为asyncF)时,进入函数内部:
- 按序执行同步代码
- 遇到await,跳出asyncF函数,
继续执行后续代码。
当await后的异步代码执行完成之后,接着执行asyncF中的后续代码。
回调地狱-用async来优化
解决方法如下:
async function fn() {
// 发第一个请求
const res = await getDataPromise('http://localhost:3000/get')
console.log('第一个请求', res)
const res1 = await getDataPromise('http://localhost:3000/getCategory?id=' + res[0].id)
console.log('第二个请求', res1)
const res2 = await getDataPromise('http://localhost:3000/getNews?id=' + res1[0].id)
console.log('第三个请求', res2)
}
fn()
其实在很多情况下都会遇到这样的问题,我们想让一步代码按照我们想要的顺序执行,如果是按照之前的方式,一环套一环,那种嵌套方式,就会出现刚开始所展示的回调地狱问题,这样会使代码不易于阅读和维护,但是我们可以通过以上两种方法避免和修改这样的回调地狱问题,虽然Promise可以解决问题,但是es7给我们的async/await更加便捷,看起来也更加整齐。