ES7中【async...await...】讲解

简介: 上一章我们说过了Promise,其实使用上已经足够。就是在理解上,还需要自己多动手敲一些代码;今天来说说另一个异步请求,是ES7中的新方法async...await...。那么我们知道了异步请求的优势,也知道可以使用回调函数或者更好的方法Promise来处理异步,那么为什么还要有引入新的异步方法...

上一章我们说过了Promise,其实使用上已经足够。就是在理解上,还需要自己多动手敲一些代码;今天来说说另一个异步请求,是ES7中的新方法async...await...

那么我们知道了异步请求的优势,也知道可以使用回调函数或者更好的方法Promise来处理异步,那么为什么还要有引入新的异步方法?

答案是Promise也有缺点:
首先Promise的代码还达不到很简洁的程度(如果有太复杂的异步,代码也会很复杂,可读性不高);
其次不能像同步代码一样方便获取到错误信息;

那么async/await怎么用,我们从字面意思理解:async:异步;await:等待

async 是异步的意思,是一个关键字,将 async 关键字放在函数前边,表示某个函数就是一个异步函数,这样就不会影响下边线程的执行顺序,那么为什么有这个关键字就会变成异步请求?我们打印一下带有关键字的函数看一下:

async function foo(n){
    return n
  }
console.log(foo(222))

控制台会打印出这样:

image

会神奇的发现,打印出来的是一个带有Promise对象,并且resolved完成状态,结果返回了222。

所以,async函数是包装成了Promise对象作为的返回值 => Promise.resolve(value)

await是等待的意思,放在要异步操作的方法前边。在异步函数当中,等待一段要发生的代码,返回后再向下执行,在没返回值之前,当前异步函数中await后的代码暂不执行。我们看两个重要的例子,仔细看一下

// 随便写一个延迟函数
function result() {
    setTimeout(() => {
        console.log('异步请求')
    }, 2000);
}

// 然后使用这个方法,先用一个await
async function foo(){
    console.log('111')
    await result();
    console.log('222');
  }
foo()
console.log('333')

image

打印结果如上,函数照常执行,所以先打印了111,然后遇到了await等待关键字,发起了异步请求,所以222是在333之后打印的,在等待2秒之后,最后打印出“异步请求”。

那么如果我把await关键字去掉会怎么样?

// 随便写一个延迟函数
function result() {
    setTimeout(() => {
        console.log('异步请求')
    }, 2000);
}

// 然后使用这个方法,先用一个await
async function foo(){
    console.log('111')
    result();
    console.log('222');
  }
foo()
console.log('333')

结果是:

image

可以看出,222不再受到await影响,按照了111、222、333正常打印。

问题来了:

  1. 那await加与不加有什么用呢?2秒钟后不都可以打印出“异步请求”四个字吗?
  2. 上边所说的 “ 在异步函数当中,await等待一段要发生的代码,返回后再向下执行,在没返回值之前,当前异步函数中await后的代码暂不执行 ” 这句话也没有得到验证,222照常打印出来,又是什么原因?

原因请注意上述代码,result函数并不是异步函数,仅仅只是个带有延迟的函数,如果我更改一个result函数,加上Promise,使它成为一个异步函数,我们再来看一下:

// 此刻我们写一个异步方法
function result() {
    return new Promise((resolved,reject)=>{
        setTimeout(() => {
            resolved(console.log('异步请求'))
        }, 2000);
    })
}

// 然后使用这个方法,需要用到await
async function foo(){
    console.log('111')
    await result();
    console.log('222');
  }
foo()
console.log('333')

打印结果如下:

image

先打印出111和333,2秒钟过后,打印出“异步请求”和222,所以这也是证明了 async/await 是操作异步方法,在返回结果之前,await后的代码,是不执行的。

async/await可以捕获到错误信息,利用try...catch,只需要在要捕获的地方加上这个方法即可:

function result() {
    return new Promise((resolved,reject)=>{
        setTimeout(() => {
            reject(console.log('异步请求'))
        }, 2000);
    })
}

// 然后使用这个方法,需要用到await
async function foo(){
    console.log('111')
    try{
        await result();
        console.log('222');
    }catch(err){
        console.log(err)
    }
  }
foo()
console.log('333')

image

上边的undefined就是错误信息,只不过这个案例没有错误信息;在实际项目中,有一些错误,我们就可以用这种方式捕获到错误信息,(try...catch语句用于处理代码中可能出现的错误信息),如果用在Promise当中,捕获错误信息就会很麻烦。这也是async的一个优点。

这样看起来 async/await 的写法,很像同步的写法,但是却可以像Promise一样去处理异步,这就是一种代码简洁的好处,如果有多个异步需要处理,不再需要像Promise那样很多 .then 代码横向发展,我们来做一下对比,例如有ABCD四个异步需要触发:
Promise写法

const result = () => {
  return aaa()
    .then(() => A())
    .then(() => B())
    .then(() => C())
    .then(() => D())
}

result()
  .catch(err => {
    console.log(err);
  })

async/await写法

const result = async () => {
  await A()
  await B()
  await C()
  await D()
}

result()
  .catch(err => {
    console.log(err);
  })

上述的代码,只是为了证明async/await写法的可读性会更好,我们在写项目时,在返回的结果中会做很多处理,这种写法在多层嵌套中,你就会发觉它的优势了。

以上就是简单介绍关于async/await的用法,还有很多的用法,例如取中间值,All方法等等,同学们可以进一步去查阅资料,在实际项目中,掌握以上的关键的知识点,是必要的。

有兴趣的同学也可以查询async/await的原理,包括进一步学习关于generator函数,并且可以在评论区留言,共同进步。

博主联系方式:
e-mail:avillin@163.com
weChat:VillinWeChat

欢迎提出宝贵意见

目录
相关文章
|
4月前
|
前端开发
ES7 async await return value
ES7 async await return value
|
7月前
|
JavaScript Java
event loop async await 事件循环机制
event loop async await 事件循环机制
31 0
|
8月前
|
前端开发 JavaScript 开发者
|
8月前
|
前端开发 C++ 容器
C++并发与多线程(四)async、future、packaged_task、promise、shared_future(下)
C++并发与多线程(四)async、future、packaged_task、promise、shared_future(下)
|
8月前
|
前端开发 Go C++
C++并发与多线程(四)async、future、packaged_task、promise、shared_future(上)
C++并发与多线程(四)async、future、packaged_task、promise、shared_future(上)
|
前端开发
你需要了解的ES7的async/await
你需要了解的ES7的async/await
|
前端开发
async/await实现Promise.acll()
Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且**只返回一个Promise实例**,并且**输入的所有 promise 的 resolve 回调的结果是一个数组**。
77 2
async/await实现Promise.acll()
|
内存技术
Vite:Error: Cannot find module ‘worker_threads‘
Vite:Error: Cannot find module ‘worker_threads‘
481 0
【解决报错】‘async with‘ outside async function
简介:【解决报错】‘async with‘ outside async function
async和await用法(Task)
原文:async和await用法 要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点。 如果你已经对Task很了解,那么如何使用async和await,在此主要总结了以下三点: 只有在async方法里面才能使用await操作符; await操作符是针对Task对象的; 当方法A调用方法B,方法B方法体内又通过await调用方法C时,如果方法C内部有异步操作,则方法B会等待异步操作执行完,才往下执行;但方法A可以继续往下执行,不用再等待B方法执行完。
1304 0

热门文章

最新文章