JavaScript异步(必考三座大山之三)——第四集:async-await
Posted 精通各种hello world的小希
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript异步(必考三座大山之三)——第四集:async-await相关的知识,希望对你有一定的参考价值。
前言
现在使用javascript开发的异步编程,基本上被async-await承包了,所以这个东西你不能不会。
第三集我们讲解到,要想解决异步的回调地狱,可以使用Promise对象里面内置的方法then,catch来解决回调地狱的问题,但是也是基于回调函数,但是我们接下来要学习的async-await是同步语法,可以彻底消灭回调函数。
语法介绍
在介绍语法之前,我们先对比两组代码:
1.使用Promise进行图片加载:
function loadImg(src)
const p = new Promise(
(resolve, reject) =>
const img = document.createElement('img');
img.onload = () =>
resolve(img);
img.onerror = () =>
const err = new Error(`图片加载失败 $src`);
reject(err);
img.src = src;
)
return p;
const url = 'https://class.imooc.com/static/module/marketpage2020/img/banner-icon-level0.png?t=2'
loadImg(url).then(
img =>
console.log(img.width);
return img;
).then(
img =>
console.log(img.height);
).catch(ex => console.error(ex));
2.使用async-await语法进行图片加载
function loadImg(src)
const p = new Promise(
(resolve, reject) =>
const img = document.createElement('img');
img.onload = () =>
resolve(img);
img.onerror = () =>
const err = new Error(`图片加载失败 $src`);
reject(err);
img.src = src;
)
return p;
const url = 'https://class.imooc.com/static/module/marketpage2020/img/banner-icon-level0.png?t=2'
const fn = async () =>
const img1 = await loadImg(url)
console.log(img1.width, img1.height);
fn();
执行结果是一样的,在这里就不加以展示了,代码1如果有同学看不明白的话,就到我们异步的第三集看看,知识点详细有写。
我们重点讲一下代码2:
执行过程:
1.首先我们定义了一个loadImg()函数包裹着一个新的Promise对象来加载图片。
2.其次定义了一个url常量存放图片地址
3.定义一个fn常量接收一个箭头函数,在箭头函数前面写上async关键字,因为执行await函数一定要有async关键字包裹,如果直接执行await函数就会报错
4.调用fn函数
执行结果分析:
上述的async-await语法,是使用同步的写法执行异步的代码的一种方式,很大程度上精简了代码,它是消灭异步回调的终极武器,是妥妥的香香甜甜的语法糖。
async-await和Promise的关系
async/await虽然是消灭异步回调的终极武器,但是并不是跟Promise水火不相容的,相反,两者是相辅相成。
先简单介绍一下他们的关系:
1.执行async函数,返回的是Promise对象
2.await相对于Promise的then
3.try...catch可捕获异常,代替了Promise的catch
验证第一条:
fn1 = async ()=>return "suc"
console.log(fn1());
虽然我们没有声明任何Promise,但是它‘suc’这个值封装成一个Promise对象,并且返回。相当于: return Promise.resolve('suc');
验证第二条:
const fn2 = async ()=>
const p1 = Promise.resolve('CSND');
const temp1 = await p1;
console.log(temp1);
const fn3 = async ()=>
const temp2 = await 'csnd';
console.log(temp2);
fn2();
fn3();
由此可见:await相当于Promise的内置方法then,await 'csnd'相当于Promise.resolve('csnd')
验证第三条:
const fn4 = async ()=>
const p2 = Promise.reject('err1');
try
const res = await p2
catch(ex)
console.log(ex);
fn4();
async语法捕获错误,我们可以通过try..catch的方法来捕获,相当于Promise的内置方法catch。
异步的本质
其实归根结底,async-await只是一个很好用的语法糖,虽说它是消灭异步回调的终极武器,但是JS是单线程,还得需要异步,还得基于event loop机制。
我们拿一串代码唠一下就会明白了。
const fn1 = async () =>
console.log('A')
await fn2()
console.log('B')
await fn3()
console.log('C')
function fn2()
console.log('D')
function fn3()
console.log('E')
console.log('F')
fn1();
console.log('G')
执行步骤:
1.前面定义的那几个函数肯定不会执行,因为还没有调用,所以第一个打印:F
2.调用fn1()函数,执行第二行代码,打印:A
3.调用fn2()函数,打印:D
4.执行完fn2()函数以后还没完,我们还需要执行前面的await操作。这里要敲黑板注意了:await的后面,都需要看作是异步的代码,简单来说,就是把await后面的代码封装成一个函数,然后丢给一个setTimeout函数里面,当成异步代码块去执行。所以执行同步代码,打印:G
5.同步代码执行完,启动event loop机制,按照执行顺序,打印:B
6.调用fn3()函数,打印:E(在这里给大家说一下,如果await 一个函数,先执行函数,再去执行前面的await操作)
7.打印:C
如果Promise,event loop 或者 异步概念依然比较迷茫的同学,可以翻看一下前面的内容。
创作不易,觉得笔者写得好的话希望大家点点赞和关注,今天就到这里。
以上是关于JavaScript异步(必考三座大山之三)——第四集:async-await的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript基础--------三座大山(前端面试必考)