如何避免或解决回调地狱

347 阅读3分钟

一、了解回调地狱问题

在说回调地狱之前我们首先得要了解到什么是回调地狱。我们来看一段代码,如下图所示(其中还有接口等等文件就不一一举出了,只针对回调地狱问题说明)

地狱1.png 大家先看这段代码是可以连续发三个请求,并且按顺序执行,第一个请求拿到的数据再往下走,再去拿数据,最后一环套一环,也可以理解为嵌套请求,这样写就跟套娃一样,如果一直写下去那么就会越来越夸张,阅读性就非常差,更不方便后期维护。这种写法就叫 ‘回调地狱’

二、如何去避免和解决回调地狱?

解决方法一: 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)
        })

下面对代码进行拆分解析如图所示: 地狱3.png 这样看起来代码会更好维护和优化,看起来也非常醒目。不会像之前那样无限套。

解决方法二: 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更加便捷,看起来也更加整齐。