ES6之async await

含义

  • 内置执行器
    • Generator函数的执行必须靠执行器,因此才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数如出一辙,只要一行fn()
  • 更好的语义
    • async和await,比起星号和yield,语义更清除了。async表示函数里又异步操做,await表示紧跟在后面的表达式须要等待结果。
  • 更广的适用性
    • co模块规定,yield命令后面只能时Thunk函数或Promise对象,而async函数的await命令后面,可不是Promise对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成当即resolved 的Promise对象)
  • 返回值时Promise
    • async函数的返回值时Promise对象,这比Generator函数的返回值是Iterator对象方便多了。你能够用then方法制定下一步操做。

进一步说,async函数彻底能够看做多个异步操做,包装成的一个Promise对象,而await命令就是then方法的语法糖promise

基本用法

async函数返回一个Promise对象,可使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操做完成,在接着执行函数体后面的语句异步

async function fn(){
        console.log(4)
        let f1 = await Promise.resolve(1)
        console.log(f1) // 1
        let f2 = await Promise.resolve(2)
        return f2
    }
    fn().then(res=>{
        console.log(res) // 2
    })
    console.log(3)
    // 4  3  1  2

上面代码中,函数前面的async关键字,表示函数内部有异步操做。调用该函数时,会当即返回一个Promise对象。async

function timeout(ms){
        return new Promise((resolve)=>{
            setTimeout(resolve,ms)
        })
    }
    async function fn(value,ms){
        await timeout(ms)
        console.log(value)
    }
    fn('haha',3000)

上面代码会在3秒后输出haha函数

async函数有多种使用形式。this

// 函数声明
    async function fn(){}
    // 函数表达式
    let fn1 = async function(){}
    // 对象的方法
    let obj = {async foo(){}}
    obj.foo().then(()=>console.log(111)) // 111
    // class 的方法
    class fn2{
        constructor(name){
            this.name = name;
        }
        async getName(){
            return this.name
        }
    }
    let name = new fn2('小明');
    name.getName().then(res=>console.log(res)) // 小明

语法

async函数返回一个Pormise对象。
async函数内部return语句返回的值,会成为then方法回调函数的参数code

let fn = async function(){
        return 111
    }
    fn().then(res=>{console.log(res)}) // 111

上面代码,函数fn返回的值,会被then放回回调函数接收到orm

async内部抛出错误,会致使返回的Promise对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。对象

let fn = async function(){
        throw new Error('出错了')
    }
    fn().catch(error=>{
        console.log(error); // Error: 出错了
    })
Promise对象的状态变化

async函数返回的Promise对象,碧玺等到内部全部await命令后面的Promise对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有asunc函数内部的异步操做执行完,才会执行then方法指定的回调函数。字符串

let fn = async function(){
        await new Promise((resolve)=>{
            setTimeout(resolve,3000)
        })
        await new Promise((resolve)=>{
            setTimeout(resolve,3000)
        })
        return 1
    }
    fn().then(res=>{
        console.log(res);
    })

上面代码,then回调函数会在6秒以后输出resget

await

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

let fn = async function(){
        // 等同于
        // return 1
        return await 1
    }
    fn().then(res=>{
        console.log(res); // 1
    })

上面代码中,await命令的参数是数值1,这是等同于return 1

let fn = async ()=>{
        await Promise.reject('出错了')
    }
    fn().catch(error=>{console.log(error)}) // 出错了

注意:上面代码中,await语句前面没有return,可是reject方法的参数依然传入了catch方法的回调函数。这里若是在await前面加上return,效果是同样的

注意:任何一个await语句后面的Promise对象变为reject,那么整个async函数都会中断执行

有时,咱们但愿即便前一个异步操做失败,也不要中断后面的异步操做。这时能够将第一个await放在try...catch结构里面,这样无论这个异步操做是否成功,第二个await都会执行

let fn = async ()=>{
        try{
            await Promise.reject('出错了')
        }catch(error){
            console.log(error) 
        }
        return 1
    }
    fn().then(res=>console.log(res)) // 1

另外一种写法

let fn = async ()=>{
        await Promise.reject('出错了').catch(error=>{
            console.log(error) 
        })
        return 1
    }
    fn().then(res=>console.log(res)) // 1

错误处理

若是await后面的异步操做出错,那么等同于async函数返回的 Promise 对象被reject。

let fn = async ()=>{
        await Promise.reject('出错了')
        return 1
    }
    fn()
    .then(res=>console.log(res))
    .catch(error=>{
        console.log(error) // 出错了
    })

上面代码中,函数fn执行后,await后面的Promise对象抛出了一个错误对象,致使catca方法的回调函数被调用。

防止出错的方法,也是将其放在try...catch代码块中

let fn = async ()=>{
        try{
            await Promise.reject('出错了')
        }catch(error){
            console.log(error);
        }
        return 1
    }
    fn()
    .then(res=>console.log(res)) // 1

若是有多个await命令,能够统一放在try...catch

相关文章
相关标签/搜索