1.掌握async和await
2.掌握promise
3.两种区别
1.async
执行async函数,返回的都是promise对象
- async function fun() {
- return 1
- }
- console.log(fun());//打印出一个promise函数

2.await
Promise.then 成功的情况对应await
- async function test3(){
- const p3=Promise.resolve(3)
-
- //then方法
- p3.then(data=>{console.log('data',data);})//3
-
- // await方法
- const data=await p3
- console.log('data111',data);//3
- }
- test3()
await会把普通值封装成Promise对象,然后它有相当于then()方法,接着去解析拿到结果,以下两个函数写法不同,输出结果都一致
- async function test4() {
- const data4 =await 4
- console.log('data4',data4);
-
- }
- //4
- async function test4() {
- await Promise.resolve(4).then(data=>{
- console.log('data444444',data);
- })
-
- }
3.捕捉错误
Promise.catch 异常的情况 对应 try....catch
- async function test5(){
- const p5=Promise.reject(6)
- try{
- const data5=await p5
- console.log('data5',data5);
- }catch(e){
- console.log('e',e);
- }
- }
Promise:
Promise特点——异步无等待,所以当没有await语句执行async函数,它就会立即执行,返回一个Promise对象,非阻塞,与普通的Promise对象函数一致
- new Promise((resolve,reject)=>{
- //reject(111)//失败,此时执行catch和finally
- resolve(100)//成功,此时执行then和finally
- }).then(data=>{//then后面的为回调函数
- console.log(data);
- }).catch(err=>{
- console.log('err',err);
- }).finally(()=>{
- console.log('成功失败都执行');
- })
- new Promise((resolve,reject)=>{
- resolve(100)
- }).then(data=>{
- console.log('data',data);//100
- return data*2 //返回一个Promise方法
- }).then(res=>{
- console.log('res',res);//200,捕获上一个then返回的值200
- })
- // all方法,接收promise的一个数组
- // race方法
- const createPromise=(delay,flag=true)=>{
- return new Promise((resolve,reject)=>{
- setTimeout(()=>{
- flag?resolve(`成功${delay}`):reject(`失败${delay}`)
- },delay)
- })
- }
-
- Promise.all([createPromise(1000)],
- [createPromise(1500)],
- [createPromise(1000)]).then(res=>{
- console.log('成功',res);
- }).catch(err=>{
- console.log('失败',err);
- })
-
- // 无论成功还是失败,第一个返回的值都会被当做结果返回
- Promise.race([createPromise(1000)],
- [createPromise(1500,false)],
- [createPromise(1000)]).then(res=>{
- console.log('成功',res);
- }).catch(err=>{
- console.log('失败',err);
- })
面试题:
- async function async1(){
- console.log('async1 start');
- await async2();//用于等待一个Promise对象,await表达式会暂停当前 async function的执行,等
- 待Promise 处理完成
- console.log('async1 end')//从async2执行完后 会返回async1中执行剩余代码 这个过程就是
- process.nextTick() ,算微任务
- }
- async function async2 () {
- console.log('async2');
- console.log('2222222');
- setTimeout(()=>{
- console.log('asyncTimeOut');
- },20)
- return 4
- }
- async2().then(data=>{
- console.log('dara',data);
- })
- console.log('script start');
- setTimeout(function () {
- console.log('setTimeout')
- },0);
- async1();
- new Promise(function (resolve) {
- console.log('promise1');
- resolve()
- }).then(function () {
- console.log('promise2')
- });
- console.log('script end')
分析一下这个题目:首先从上至下依次执行
- async function async1(){
- console.log('async1 start');
- await async2();
- console.log('async1 end')
- }
- async function async2 () {
- console.log('async2');
- console.log('2222222');
- setTimeout(()=>{
- console.log('asyncTimeOut');
- },20)
- return 4
- }
-
函数声明还未被调用什么也不输出
- async2().then(data=>{
- console.log('dara',data);
- })
async2函数被调用,先运行同步代码
- console.log('async2');
- console.log('2222222');
运行到定时器属于异步代码,加入到宏任务队列,记作宏任务1,
setTimeout(()=>{
console.log('asyncTimeOut');
},20)
因为async的返回值是一个Promise对象,所以返回值return 4是一个promise对象,需要使用then或者await来调用,then后面属于异步中的微任务,记作未微任务1
- .then(data=>{
- console.log('dara',data);
- })
至此输出:
async22222222
继续向下执行:
console.log('script start');
至此输出:
async22222222
script start
继续向下执行,遇到一个异步任务定时器,将该定时器存入到宏任务,标记为宏任务2
- setTimeout(function () {
- console.log('setTimeout')
- },0);
继续向下执行,执行了async1(),该函数使用了关键字async,在没有遇到await之前照常运行,所以此时会输出async1 start,遇到await后,await会等待一个promise对象返回,await后调用了async2(),在async2()里面console.log('async2'); console.log('2222222');不是返回的数据,也就不是一个promise对象,所以此时直接输出 async2,2222222,还有一个定时器此时加入到宏任务记作宏任务3,将await加入到微任务连同后面的console.log('async1 end'),记作微任务2
- async1();
-
-
- async function async1(){
- console.log('async1 start');
- await async2();
- console.log('async1 end')
- }
-
- async function async2 () {
- console.log('async2');
- console.log('2222222');
- setTimeout(()=>{
- console.log('asyncTimeOut');
- },20)
- return 4
- }
至此输出:
async22222222
script start
async1 start
async2
2222222
疑问:
为什么async start输出以后,调用async2输出async2下面的打印不执行了,直接执行Promise了
解答:
从async2执行完后 会返回async1中执行剩余代码 这个过程就是process.nextTick() ,算微任务
执行到 await async2(),发现 async2 也是个 async 定义的函数,所以直接执行了“console.log('async2')”,同时async2返回了一个Promise,划重点:此时返回的Promise会被放入到回调队列中等待,await会让出线程(js是单线程),接下来就会跳出 async1函数 继续往下执行。
继续向下执行:Promise.resolve属于同步任务,直接输出promise1,then中的代码需要加入到微任务,记作微任务3
- new Promise(function (resolve) {
- console.log('promise1');
- resolve()
- }).then(function () {
- console.log('promise2')
- });
至此输出:
async22222222
script start
async1 start
async2
2222222
promise1
继续执行代码,毫无疑问直接输出script end
console.log('script end')
至此输出:
async22222222
script start
async1 start
async2
2222222
promise1
script end
此时执行栈完成任务完成,立即去微任务队列寻找任务,此时微任务有3个,依次执行,
微任务1输出:data:4
微任务2输出:4
async1 end
微任务3输出:promise2
微任务执行结束,开始执行宏任务,宏任务也有3个,
宏任务1:为一个20s的定时器,此时时间还没到,等待执行
宏任务2:为一个0s的定时器,此时时间已到,可以执行,输出setTimeOut,此时重新轮询
查到宏任务1,和宏任务3,因为1和3都是20s,1先进入任务队列先执行宏任务1,输出asyncTimeOut,再执行宏任务3,输出asyncTimeOut
自此所有结果出来:
async2
2222222
script startasync1 start
async2
2222222
promise1
script end
dara 4
async1 end
promise2setTimeout
asyncTimeOutasyncTimeOut
1.对await的深度理解
await
await即等待,用于等待一个Promise对象。它只能在异步函数async function中使用,否则会报错
它的返回值不是Promise对象而是Promise对象处理之后的结果await表达式会暂停当前async function的执行,等待Promise处理完成。若Promise正常处理(fulfilled),其回调的resolve函数参数作为await表达式的值,继续执行async function,若Promise处理异常(rejected),await表达式会把Promise的异常原因抛出。如果await操作符后的表达式的值不是一个Promise,那么该值将被转换为一个已正常处理的Promise。
2.await与promise的区别
1、不再需要多层.then方法
假设一个业务分很多步骤完成,并且每个步骤都是异步,依赖上一个步骤的结果。
- function takeLongTime(n) {
- return new Promise(resolve => {
- setTimeout(() => resolve(n + 200), n);
- });
- }
-
- function step1(n) {
- console.log(`step1 with ${n}`);
- return takeLongTime(n);
- }
-
- function step2(n) {
- console.log(`step2 with ${n}`);
- return takeLongTime(n);
- }
-
- function step3(n) {
- console.log(`step3 with ${n}`);
- return takeLongTime(n);
- }
-
- // Promise方式
- function doIt() {
- console.time("doIt");
- const time1 = 300;
- step1(time1)
- .then(time2 => step2(time2))
- .then(time3 => step3(time3))
- .then(result => {
- console.log(`result is ${result}`);
- console.timeEnd("doIt");
- });
- }
-
- doIt();
-
- // async await方式
- async function doIt() {
- console.time("doIt");
- const time1 = 300;
- const time2 = await step1(time1);
- const time3 = await step2(time2);
- const result = await step3(time3);
- console.log(`result is ${result}`);
- console.timeEnd("doIt");
- }
- doIt();
2、可以对Promise进行并行处理
- console.time('total time')
- await Promise.all([
- (async()=>console.log('输出结果:',await waitFun(3000)))(),
- (async()=>console.log('输出结果:',await waitFun(2000)))(),
- (async()=>console.log('输出结果:',await waitFun(1000)))(),
- ]);
- console.timeEnd('total time')
- /**
- * 输出结果: 1000
- * fn3 time: 1009 ms
- *
- * 输出结果: 2000
- * fn2 time: 2010 ms
- *
- * 输出结果: 3000
- * fn1 time: 3011 ms
- *
- * total time: 3011 ms
- */