async-await语法解决回调地狱

436 阅读2分钟

async-await语法

async,await 是es7中新增的语法,用来进一步改进异步代码的写法,是promise升级版!

async

async函数返回一个 Promise 对象。

async函数内部return语句返回的值是Promise 对象的值

function f1 () {
  return 1
}
async function f2 () {
  return 1
}
async function f3 () {}
const r1 = f1()
const r2 = f2()
const r3 = f3()
console.log(r1) // 1
console.log(r2) // Promise, resolved(1)
console.log(r3) // Promise, resolved(undefined)
r2.then(res => { console.log(res) })
r3.then(res => { console.log(res) })

await 命令

await的外层函数必须有一个async.

正常情况下,await命令后面是一个 Promise 对象,返回该promise的值。如果不是 Promise 对象,就直接返回对应的值。

<script>
    async function f() {
        const p = new Promise((resolve,reject)=>{
            resolve(100)
        })
        const a = 1
    
        // await 等待promise的状态变化完成(pending->resolved, pending->rejected)
        // 取出promise的值
        const b = await p 

        console.log(a,b)
    }

    f()
</script>

async函数内部的执行流程

在执行async函数(设名为asyncF)时,进入函数内部:

- 按序执行同步代码
- 遇到await,跳出asyncF函数,

继续执行后续代码。

当await后的异步代码执行完成之后,接着执行asyncF中的后续代码。

const p1 = new Promise((resolve, reject) => {
  setTimeout(()=>resolve(100), 3000)
})

async function f () {
  console.log('开始执行f')
  var a = await p1
  console.log('p1完成了')
  console.log(a)
  return 1
}

console.log('主函数运行...')
const res = f()
console.log('f()完成,返回值是', res)
res.then(res => { console.log(res) })

执行结果是

主函数运行...
开始执行f
f()完成,返回值是 Promise { <pending> }
----此处等了3s----
p1完成了
100
1

回调地狱-用async来优化

        //封装普通函数发ajax
        function getData({url,success}) {
            const xhr = new XMLHttpRequest()
            xhr.open('get', url)
            xhr.onreadystatechange = function (){
                if(this.readyState === 4){
                    // 加载完成
                    const d = JSON.parse(xhr.responseText);
                    success(d)
                }
            }
            xhr.send()
        }
        //利用promise对象封装ajax
        function getDataPromise (url) {
            return new Promise((resolve,reject) => {
                const xhr = new XMLHttpRequest()
                xhr.open('get', url)
                xhr.onreadystatechange = function (){
                    if(this.readyState === 4){
                        // 加载完成
                        const d = JSON.parse(xhr.responseText);
                        resolve(d)
                    }
                }
                xhr.send()
            })
        }
        
        //普通函数陷入回调地狱
        getData({
            url:'http://localhost:3000/get',
            success: (data)=>{
                getData({
                    url:'http://localhost:3000/getCategory?id=1',
                    success: data => {
                        console.log(data)
                        getData({
                            url:'http://localhost:3000/getNews?id='+data[0].id,
                            success: data => {
                                console.log(data)
                        }
                    })
                }
            })
        }})
        
        //使用async-await解决回调地狱
        async function get() {
            const res1 = await getDataPromise('http://localhost:3000/get')
            const res2 = await getDataPromise('http://localhost:3000/getCategory?id='+res1[0].id)
            const res3 = await getDataPromise('http://localhost:3000/getNews?id='+res2[0].id)
            console.log(res3)
        } 

        get()