ES8 async await 详解

本文详细介绍了JavaScript中的异步处理,从传统的回调函数到Promise的链式调用,再到ES6引入的async/await语法。通过实例展示了如何避免回调地狱,如何处理异常,以及如何实现并行操作。async函数使得异步代码更接近同步风格,提高代码可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步函数 async function()
1.作用
避免有更多的请求操作,出现多重嵌套,也就是俗称的“回调地狱”,比如登录之后获取用户信息操作

this.$http.jsonp('/login', (res) => {
  this.$http.jsonp('/getInfo', (info) => {
    // do something
  })
})

因此提出了ES6的Promise,将回调函数的嵌套,改为了链式调用:

var promise = new Promise((resolve, reject) => {
  this.login(resolve);
})
.then(() => {
  this.getInfo()
})
.catch(() => {
  console.log('Error')
})

2.明方式
异步函数存在以下四种使用形式:

  1. 函数声明: async function foo() {}
  2. 函数表达式: const foo = async function() {}
  3. 对象的方式: let obj = { async foo() {} }
  4. 箭头函数: const foo = async () => {}

3支持返回Promise和同步的值
async用于定义一个异步函数,该函数返回一个Promise
如果async函数返回的是一个同步的值,这个值将被包装成一个理解resolve的Promise,等同于return Promise.resolve(value)。
await用于一个异步操作之前,表示要“等待”这个异步操作的返回值。await也可以用于一个同步的值。

    //async await
    //返回Promise
    let timer = async function timer() {
        return new Promise((reslove, reject) => {
            setTimeout(() => {
                reslove('a');
            }, 1000);
        })
    }
    timer().then(result => {
        console.log(result);
    }).catch(err => {
        console.log(err.message);
    })

    //返回同步的值
    let sayHello = async function sayHello() {
        let hi = 'hello world'//等同于return Promise.resolve(hi);
        return hi
    }
    sayHello().then(res => {
        console.log(res)
    }).catch(err => {
        console.log(err.message);
    })

4对异常的处理
首先来看下Promise中对异常的处理
1.使用reject

let promise = new Promise((reslove, reject) => {
  setTimeout(() => {
    reject('promise使用reject抛出异常')  
  }, 1000)
})
promise().then(res => {
  console.log(res)
})
.catch(err => {
  console.log(err)     //'promise使用reject抛出异常'
})

2.使用new Error()

let promise = new Promise((reslove, reject) => {
    throw new Error('promise使用Error抛出异常') //使用throw异常不支持放在定时器中
})
promise().then(res => {
  console.log(res)
})
.catch(err => {
  console.log(err.message)     //'promise使用Error抛出异常'
})

3.reject一个new Error()

    let promise = new Promise((resolve, reject) => {
    
        setTimeout(() => {
            reject(new Error('promise抛出异常'));
        }, 1000);
    })

    promise.then(res => {
        console.log(res);
    })
    .catch(err => {
        console.log(err.message);  //'promise抛出异常'
    })

async对异常的处理也可以直接用.catch()捕捉到

    //async抛出异常
    let sayHi = async sayHi => {
            throw new Error('async抛出异常');
    }
    sayHi().then(res => {
        console.log(res);
    })
    .catch(err => {
        console.log(err.message);
    })

和Promise链的对比:
我们的async函数中可以包含多个异步操作,其异常和Promise链有相同之处,如果有一个Promise被reject()那么后面的将不会再进行。

    let count = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                reject('promise故意抛出异常')
            }, 1000);
        })
    }
    let list = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve([1, 2, 3])
            }, 1000);
        })
    }

    let getList = async () => {
        let c = await count()
        console.log('async')    //此段代码并没有执行
        let l = await list()
        return { count: c, list: l }
    }
    console.time('start');
    getList().then(res => {
        console.log(res)
    })
    .catch(err => {
        console.timeEnd('start')
        console.log(err)
    })
    
    //start: 1000.81494140625ms
    //promise故意抛出异常

可以看到上面的案例,async捕获到了一个错误之后就会立马进入.catch()中,不执行之后的代码
5并行
上面的案例中,async采用的是串行处理

count()list()是有先后顺序的

let c = await count()
let l = await list()

实际用法中,若是请求的两个异步操作没有关联和先后顺序性可以采用下面的做法

let res = await Promise.all([count(), list()])
return res

//res的结果为
//[ 100, [ 1, 2, 3 ] ]

案例详情为:

let count = ()=>{
    return new Promise((resolve,reject) => {
        setTimeout(()=>{
            resolve(100);
        },500);
    });
}

let list = ()=>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve([1,2,3]);
        },500);
    });
}

let getList = async ()=>{
    let result = await Promise.all([count(),list()]);
    return result;
}
console.time('begin');
getList().then(result => {
    console.timeEnd('begin');  //begin: 505.557ms
    console.log(result);       //[ 100, [ 1, 2, 3 ] ]
}).catch(err => {
    console.timeEnd('begin');
    console.log(err);
});

我们将count()list()使用Promise.all()“同时”执行,这里count()list()可以看作是“并行”执行的,所耗时间将是两个异步操作中耗时最长的耗时。
最后得到的结果是两个操作的结果组成的数组。我们只需要按照顺序取出数组中的值即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值