likes
comments
collection
share

用大白话讲懂async/await的基本用法和使用场景

作者站长头像
站长
· 阅读数 3

async

async声明function是一个异步函数,返回一个promise对象,可以使用then方法添加回调函数。

1、async异步函数的执行流程

默认情况下和普通函数的执行流程是没什么区别的

async function foo() {
    console.log("foo function start~")
    console.log("内部的代码执行1")
    console.log("foo function end~")
}

console.log("start")
foo()
console.log("end")

// 按顺序输出
// start
// foo function start~
// 内部的代码执行1
// foo function end~
// end

2、async异步函数的返回值

async函数的返回值一定为promise对象,promise对象的结果由async函数执行的返回值决定。

2.1、async函数返回值为promise对象

async function foo() {}

// 异步函数的返回值一定是一个promise
console.log(foo()) // Promise { undefined }

2.1、async函数返回一个数字

async function foo() {
    return 123
}

foo().then(res => {
    console.log(res) // 输出123
}).catch(err => {
    console.log(err)
})

2.2、async函数默认返回

async function foo() {}

foo().then(res => {
    console.log(res) // 输出'undefined'
}).catch(err => {
    console.log(err)
})

2.2、async函数返回一个Promsie对象

async function foo() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("hehehehe")
        }, 200)
    })
}

foo().then(res => {
    console.log(res) // 输出'hehehehe'
}).catch(err => {
    console.log(err)
})

await

await操作符只能在async异步函数内部使用。如果一个Promise被传递给一个await操作符,await将等待Promise 正常处理完成并返回其处理结果,也就是说它会阻塞后面的代码,等待 Promise对象结果。如果等待的不是Promise 对象,则返回该值本身。

1、await后面跟上一个数字

async function foo() {
    const res1 = await 123
    console.log(res1) // 输出123
}
foo()

2、await后面跟上一个Promsie对象

只有当Promsie的状态变为Fulfilled,后面的代码才会执行。

function requestData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('输出')
        }, 1000);
    })
}

async function foo() {
    // 如果没有结果,后面的代码是不会执行的,可以把上面的resolve注释掉试试
    const res1 = await requestData() 
    console.log(res1) // '输出'
    console.log("后面的代码1") // '后面的代码1'
}

foo()

3、await后面跟上reject值

如果await后面的异步操作出错,那么等同于async函数返回的 Promise对象被reject。后面的代码将不会再执行,我们可以使用try...catch进行包裹防止出错。

function requestData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('输出')
        }, 1000);
    })
}

async function foo() {
    try {
        const res1 = await requestData() // 这里如果是reject 不会往后执行了
        console.log('后续代码')
    } catch (error) {

    }
}
foo()

async/await的使用场景

function fn1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('我')
        }, 1000)
    })
}

function fn2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('喜欢')
        }, 200)
    })
}

function fn3() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('你')
        }, 100)
    })
}

fn1().then(res => {
    console.log(res)
    return fn2()
}).then(res => {
    console.log(res)
    return fn3()
}).then(res => {
    console.log(res)
})

// 1s后输出'我', 再过200ms后输出'喜欢',再过100ms后输出'你'

这么做是没问题的,但是如果嵌套的多了,不免有点不雅观,在开发中,为了代码的简洁性,我们也常用async/await来解决。

async function getData() {
    let res1 = await fn1()
    console.log(res1)
    let res2 = await fn2()
    console.log(res2)
    let res3 = await fn3()
    console.log(res3)
}
getData()
// 1s后输出'我', 再过200ms后输出'喜欢',再过100ms后输出'你'

这样写还有以下好处:

1、更加灵活,直观地控制函数什么时候继续执行、暂停执行。 比如我现在有个需求,先请求完接口3,再拿接口3返回的数据,去当做接口4的请求参数。(在拿接口3的数据的后,我们可以做任何的处理,再拿最后的结果去作为接口4的请求参数,这个过程就相当于对函数进行了暂停,执行的操作)

function fn4(val) {
    return new Promise(resolve => {
        setTimeout(() => {
            switch(val) {
                case 0:
                    resolve('我喜欢你')
                case 1:
                    resolve('你不喜欢我')
            }
        })
    })
}

async function getData() {
    let res1 = await fn3()
    res1 = res1 == '我' ? 0 : 1
    let res2 = await fn4(res1)
    console.log(res2)
}
getData()
// 输出'你不喜欢我'

2、等到所有的结果都有返回值后,才对所有的返回值进行处理。 比如我现在有个需求,我想拿到所有接口的数据,再对数据做一个总的输出。

async function getData() {
    let res1 = await fn1()
    let res2 = await fn2()
    let res3 = await fn3()
    console.log(res1 + res2 + res3)
}
getData()
// 1.3s后输出'我喜欢你'

总结:

1、async函数返回的一定是一个Promise对象;

2、await只能在async函数中使用,不然会报错;

3、async/await的使用能使代码看起来更简洁;

4、async/await的使用更加灵活,直观地控制函数什么时候继续执行、暂停执行;

5、async/await的使用能更方便地等到所有的结果都有返回值后进行处理;