async/awit基础总结

500 阅读3分钟

async

async是用来生成异步函数的,它的后面可以是函数声明,函数表达式,箭头函数等。async函数生成的是一个promise,后面可以接.then或者.catch进行处理。如果async函数里面return一个数字或者字符串或者promise,那么它就会返回一个成功的promise,异步函数捕获的值为那个数字或者字符串。

 let p = async function add(){
      return 'haha'
   }
 p().then(console.log)
 //haha

如果抛出一个错误,那么就是返回一个失败的promise,异步函数捕获的的错误值为throw的值

let p = async function add(){
            throw 3
        }
        p().then((res)=>{
            console.log(res)
        },(e)=>{
            alert(e)
        })
// 会弹出3

但是拒绝的promise的错误不会被异步函数捕获。

let p = async function add(){
            Promise.reject(3)
        }
        p().then((res)=>{
            console.log(res)
        },(e)=>{
            alert(e)
        })
        //报错

await

因为async函数是异步函数,他不会马上完成任务,但是它相对于需要调用next()方法来逐步执行的生成器函数(Generator)来说,他又实现了自动执行。所以它自然需要一种暂停执行或者重新执行的能力。使用await可以使异步函数暂停执行,等待期约的解决。

let p = async ()=>{
            console.log(1)
            let p1 = await Promise.resolve(3)
            console.log(p1)
            console.log(4)
        }
        p()
        console.log(2)
        // 1 2 3 4

从上面的代码可以看出,await后面的代码被延后执行了,也就是等待Promise.resolve()被解决,并且有了返回值之后才会执行后面的。

项目中,下面的代码是比较常见的用法

let axios = function(type,url){
           return new Promise((resolve,reject)=>{
            let xhr = new XMLHttpRequest();
            xhr.open(type,url)
            xhr.send()
            xhr.onreadystatechange=function(){
                if(xhr.readyState===4){
                    if(xhr.status>=200&&xhr.status<300){
                        // 这种情况代表发送成功
                        resolve(Response)
                    }
              }
            }
           })
       };
       let p= async()=>{
            console.log('在接受数据前的操作')
            let res=await axios('GET','promise.php')
            console.log(res)
            console.log('在接受数据之后的操作')
       }
       p()

await抛出错误的获取方式

1、await后面如果是promise.reject()或者是抛出的错误,那么async会立刻返回一个失败的promise,捕获到的值是抛出的错误。那么await后面的操作就不会在执行了

let p =async function pp(){
            await (()=>{
                throw 3
            })()
            console.log(4)
        }
        p().catch(console.log)
 // 3
let p =async function pp(){
            await Promise.reject(3)
            console.log(4)
        }
        p().catch(console.log)
   // 3

2、try/catch:可以直接利用try/catch来进行捕获错误,那么他后面的操作还是会被执行的

let p =async function pp(){
           try {
                await Promise.reject(3)
           } catch (error) {
              console.log(error) 
           }
            console.log(4)
        }
       p()
 // 3 4

异步函数策略

1、实现sleep

在不堵塞程序的情况下,让异步函数暂停执行一段时间,其本质还是使用setTimeout(),等待一段时间之后,再让await后面的promise的状态发生改变,await才能得到resolve的值。然后后面的程序才能够执行。

 function sleep(delay){
        return new Promise((resolve)=>{
            setTimeout(resolve,delay)
        })
    }
    async function wait(){
        await sleep(3000)
        console.log(4)
    }
    wait()
  // 等待3秒后输出:4

2、平行执行

function time(id){
            let t = Math.random*1000
            return new Promise((resolve)=>{
                setTimeout(()=>{
                    console.log(`${id},finished`)
                    resolve()
                },t)
            })
        }
        let p=async ()=>{
            let t0 = Date.now()
            await time(1)
            await time(2)
            await time(3)
            console.log(Date.now()-t0)
        }
        p()
 // 1,finished;2,finished;3,finished;6

虽然所有的Promise之间并没有什么依赖关系,但是还是以此执行的。

3、串行执行promise

async function two(x){
            return x+2
        };
        async function three(x){
            return x+3
        };
        async function five(x){
            return x+5
        }
       async function ten(x){
        for (const fn of [two,three,five]){
            x=await fn(x)
        }
        return x
       } 
       ten(5).then(console.log)

使用async/await执行串行期约更加的方便!