在讲解async和await之前,我们先去创建三个普通的函数,如下:
<template> </template> <script> export default { created() { function funOne() { return '111111' } function funTwo(){ return '222222' } function funThree(){ return '333333' } function run (){ console.log(funOne()) console.log(funTwo()) console.log(funThree()) } run(); } } </script> <style> </style>
从上面的例子我们就可以看出,其实我们就是创建了三个普通的函数:funOne(),funTwo(),funThree();然后我们又再次创建一个普通函数:run()。
接着,我们去调用run()函数,然后在run()函数里面去调用其他三个函数,即funOne(),funTwo(),funThree()。
但是,再看看我接下来所说的内容。
假如说,我们给第二个函数funTwo()添加一个请求,例如向后端发送一个请求。
我们知道,在我们发送请求的时候,是需要得到对方服务器的一个响应的,响应的话就会需要有一定的时间才能来完成这个响应。
下面我们用setTimeOut来简单模拟一下这个请求,如下:
<template> </template> <script> export default { created() { function funOne() { return '111111' } function funTwo() { setTimeout(() => { return '222222' }, 3000) } function funThree() { return '333333' } function run() { console.log(funOne()) console.log(funTwo()) console.log(funThree()) } run(); } } </script> <style> </style>
从上面的打印结果来看,可以看出第二个函数funTwo()打印出来的结果是 'unfinished' 而不是 '222222',为什么是 'unfinished' 呢?
因为从打印的结果来看,我们可以看出就是,在函数funTwo()还没有执行完毕的时候,而函数run就已经执行完毕了,为啥呢?
因为我们在函数funTwo()中添加了一个setTimeout,加了一个延迟回调,相当于一个异步请求,这个是我们模拟的一个请求,从向后端发送请求到得到后端返回的响应,整个来回过程是需要花费时间的,所以才导致了这个结果的产生:在函数funTwo()还没有执行完毕的时候,而函数run就已经执行完毕了,因此所以说,函数funTwo()打印出来的结果是 'unfinished' 而不是 '222222'。
从上面的解释我们可以看出,第二个函数funTwo()调用的时候变成一个异步请求,代码执行的时候反应速度不如其他另外两个同步函数:funOne()和funThree()。
那么我们该如何把异步请求改变成同步请求呢?
接下来,我们给函数funTwo()添加一个Promise,看看会发生什么?
从打印的结果来看,在我们给函数funTwo()添加一个Promise的时候,打印的结果居然是一个Promise对象。
没错,就是返回了一个Promise对象!
Promise是干啥用的?
Promise我们应该都熟悉,其实就是处理异步请求的,把异步请求变成同步请求的,同时返回一个Promise对象。
为啥返回的是一个Promise对象,而不是返回我们真正想要的结果 '222222' 呢?
我们知道Promise有很多方法,比如最常见的就是then()和catch()方法,then()方法可以处理返回的结果,而catch()方法可以捕获异常。
接下来,看看如何返回我们想要的数据呢?
我们可以使用then()方法来返回我们想要的数据。
<template> </template> <script> export default { created() { function funOne() { return '111111' } function funTwo() { return new Promise((resolve,reject) => { setTimeout(() => { resolve('222222') }, 3000) }) } function funThree() { return '333333' } function run() { console.log(funOne()) funTwo().then((res) => { console.log(res) }) console.log(funThree()) } run(); } } </script> <style> </style>
从打印的结果来看,确实返回我们想要的结果 '222222',但是,仔细一看你会发现返回的结果顺序跟我们想象中的不一样,我们想象中的返回结果应该是什么样的呢?
应该是:‘111111’、‘222222’、‘333333’,这才是我们想要的结果返回顺序。
我们上面也说了,Promise不是用来处理异步的吗?把异步变成同步的,为啥返回的结果顺序还跟异步似的?
下面我来解释一下为什么会出现这种情况。
刚才我们在返回我们想要的结果的时候,是不是调用了一个Promise的一个then()方法?
对,没错,就是这个then()方法!
Promise是同步的,没错!
但是Promise的then()方法是异步的,因为then()方法它里面是一个回调函数!所以,才导致返回的结果顺序不是我们想要的。
那我们接下来该怎么办呢?
别慌,讲到现在还没进入主题呢,下面我们期待已久的主角要闪亮登场了!
async 是第一个主角!await是第二个主角!
async和await是什么?又是干什么用的?
async和await是ES7提供的,可以简化Promise操作,提高Promise代码的阅读性和理解性;
async和await结合起来,可以使得异步调用不返回Promise对象,而是直接把then回调函数的第一个形参result给返回出来,使得代码更简洁,提高开发效率,也可以保证异步调用的顺序执行,减少回调地狱出现程度。
async该怎么用?该怎么写?
async使用在函数的前面,把函数变成一个异步函数,返回值是一个Promise对象。
<template> </template> <script> export default { created() { async function fun(){ return '444444' } console.log(fun()) } } </script> <style> </style>
从打印的结果来看,可以看出返回的的确是一个Promise对象。
那我们怎么获取到值 ‘444444’ 呢?
其实,async和Promise作用都是一样的,都是解决异步编程的一种方法,使异步程序看起来像执行同步一样。
Promise是ES6提出的一种解决异步编程的一种方法;而async是ES7提出的另外一种解决异步编程的一种新方法,而且async是基于Promise实现的,同样继承了Promise的相关方法,比如then()方法。
那我们该怎么做才能获取到值呢?
<template> </template> <script> export default { created() { async function fun(){ return '444444' } fun().then((res) => { console.log(res) }) } } </script> <style> </style>
await该怎么用?该怎么写呢?
await的用法,有点特殊,它不能单独使用,也不能使用在普通的函数当中,必须结合async使用,并且只能使用在async声明的函数当中。
接下来,我们就可以使用await结合async来解决我们之前困惑很久的调用run()函数里面的异步调用顺序执行问题。
<template> </template> <script> export default { created() { function funOne() { return '111111' } function funTwo() { return new Promise((resolve,reject) => { setTimeout(() => { resolve('222222') }, 3000) }) } function funThree() { return '333333' } async function run() { console.log(funOne()) console.log(await funTwo()) console.log(funThree()) } run(); } } </script> <style> </style>
反过来再看看打印结果,是不是正是我们所需要的数据,没错,就是我们期待已久的结果返回顺序。
async和await的作用:
(1)替代then()
(2)保证各个异步调用顺序执行,减少回调地狱
async和await的好处:
(1)代码更简洁,结构更清晰,便于阅读和理解
(2)提高开发效率