• async 和await和promise


    学习目标:

    1.掌握async和await

    2.掌握promise

    3.两种区别


    学习内容:

    1.async

    执行async函数,返回的都是promise对象

    1. async function fun() {
    2. return 1
    3. }
    4. console.log(fun());//打印出一个promise函数

    2.await

    Promise.then 成功的情况对应await

    1. async function test3(){
    2. const p3=Promise.resolve(3)
    3. //then方法
    4. p3.then(data=>{console.log('data',data);})//3
    5. // await方法
    6. const data=await p3
    7. console.log('data111',data);//3
    8. }
    9. test3()

    await会把普通值封装成Promise对象,然后它有相当于then()方法,接着去解析拿到结果,以下两个函数写法不同,输出结果都一致

    1. async function test4() {
    2. const data4 =await 4
    3. console.log('data4',data4);
    4. }
    5. //4
    1. async function test4() {
    2. await Promise.resolve(4).then(data=>{
    3. console.log('data444444',data);
    4. })
    5. }

    3.捕捉错误 

     Promise.catch 异常的情况 对应 try....catch

    1. async function test5(){
    2. const p5=Promise.reject(6)
    3. try{
    4. const data5=await p5
    5. console.log('data5',data5);
    6. }catch(e){
    7. console.log('e',e);
    8. }
    9. }

    Promise:

    Promise特点——异步无等待,所以当没有await语句执行async函数,它就会立即执行,返回一个Promise对象,非阻塞,与普通的Promise对象函数一致

    1. new Promise((resolve,reject)=>{
    2. //reject(111)//失败,此时执行catchfinally
    3. resolve(100)//成功,此时执行thenfinally
    4. }).then(data=>{//then后面的为回调函数
    5. console.log(data);
    6. }).catch(err=>{
    7. console.log('err',err);
    8. }).finally(()=>{
    9. console.log('成功失败都执行');
    10. })
    1. new Promise((resolve,reject)=>{
    2. resolve(100)
    3. }).then(data=>{
    4. console.log('data',data);//100
    5. return data*2 //返回一个Promise方法
    6. }).then(res=>{
    7. console.log('res',res);//200,捕获上一个then返回的值200
    8. })
    1. // all方法,接收promise的一个数组
    2. // race方法
    3. const createPromise=(delay,flag=true)=>{
    4. return new Promise((resolve,reject)=>{
    5. setTimeout(()=>{
    6. flag?resolve(`成功${delay}`):reject(`失败${delay}`)
    7. },delay)
    8. })
    9. }
    10. Promise.all([createPromise(1000)],
    11. [createPromise(1500)],
    12. [createPromise(1000)]).then(res=>{
    13. console.log('成功',res);
    14. }).catch(err=>{
    15. console.log('失败',err);
    16. })
    17. // 无论成功还是失败,第一个返回的值都会被当做结果返回
    18. Promise.race([createPromise(1000)],
    19. [createPromise(1500,false)],
    20. [createPromise(1000)]).then(res=>{
    21. console.log('成功',res);
    22. }).catch(err=>{
    23. console.log('失败',err);
    24. })

    面试题:

    1. async function async1(){
    2. console.log('async1 start');
    3. await async2();//用于等待一个Promise对象,await表达式会暂停当前 async function的执行,等
    4. Promise 处理完成
    5. console.log('async1 end')//从async2执行完后 会返回async1中执行剩余代码 这个过程就是
    6. process.nextTick() ,算微任务
    7. }
    8. async function async2 () {
    9. console.log('async2');
    10. console.log('2222222');
    11. setTimeout(()=>{
    12. console.log('asyncTimeOut');
    13. },20)
    14. return 4
    15. }
    16. async2().then(data=>{
    17. console.log('dara',data);
    18. })
    19. console.log('script start');
    20. setTimeout(function () {
    21. console.log('setTimeout')
    22. },0);
    23. async1();
    24. new Promise(function (resolve) {
    25. console.log('promise1');
    26. resolve()
    27. }).then(function () {
    28. console.log('promise2')
    29. });
    30. console.log('script end')

    分析一下这个题目:首先从上至下依次执行

    1. async function async1(){
    2. console.log('async1 start');
    3. await async2();
    4. console.log('async1 end')
    5. }
    6. async function async2 () {
    7. console.log('async2');
    8. console.log('2222222');
    9. setTimeout(()=>{
    10. console.log('asyncTimeOut');
    11. },20)
    12. return 4
    13. }

    函数声明还未被调用什么也不输出


    1. async2().then(data=>{
    2. console.log('dara',data);
    3. })

    async2函数被调用,先运行同步代码

    1. console.log('async2');
    2. console.log('2222222');

    运行到定时器属于异步代码,加入到宏任务队列,记作宏任务1

     setTimeout(()=>{

            console.log('asyncTimeOut');

        },20)

    因为async的返回值是一个Promise对象,所以返回值return  4是一个promise对象,需要使用then或者await来调用,then后面属于异步中的微任务,记作未微任务1

    1. .then(data=>{
    2. console.log('dara',data);
    3. })

    至此输出:
        async2

        2222222


    继续向下执行:

    console.log('script start');

    至此输出:
        async2

        2222222

        script start


    继续向下执行,遇到一个异步任务定时器,将该定时器存入到宏任务,标记为宏任务2

    1. setTimeout(function () {
    2. console.log('setTimeout')
    3. },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

    1. async1();
    2. async function async1(){
    3. console.log('async1 start');
    4. await async2();
    5. console.log('async1 end')
    6. }
    7. async function async2 () {
    8. console.log('async2');
    9. console.log('2222222');
    10. setTimeout(()=>{
    11. console.log('asyncTimeOut');
    12. },20)
    13. return 4
    14. }

    至此输出:
        async2

        2222222

        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

    1. new Promise(function (resolve) {
    2. console.log('promise1');
    3. resolve()
    4. }).then(function () {
    5. console.log('promise2')
    6. });

    至此输出:
        async2

        2222222

        script start

        async1 start

        async2

        2222222

        promise1


    继续执行代码,毫无疑问直接输出script end

    console.log('script end')

    至此输出:
        async2

        2222222

        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 start

    async1 start
    async2
    2222222
    promise1
    script end
    dara 4
    async1 end
    promise2

    setTimeout
    asyncTimeOut

    asyncTimeOut


    补充:

    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方法
    假设一个业务分很多步骤完成,并且每个步骤都是异步,依赖上一个步骤的结果。

    1. function takeLongTime(n) {
    2. return new Promise(resolve => {
    3. setTimeout(() => resolve(n + 200), n);
    4. });
    5. }
    6. function step1(n) {
    7. console.log(`step1 with ${n}`);
    8. return takeLongTime(n);
    9. }
    10. function step2(n) {
    11. console.log(`step2 with ${n}`);
    12. return takeLongTime(n);
    13. }
    14. function step3(n) {
    15. console.log(`step3 with ${n}`);
    16. return takeLongTime(n);
    17. }
    18. // Promise方式
    19. function doIt() {
    20. console.time("doIt");
    21. const time1 = 300;
    22. step1(time1)
    23. .then(time2 => step2(time2))
    24. .then(time3 => step3(time3))
    25. .then(result => {
    26. console.log(`result is ${result}`);
    27. console.timeEnd("doIt");
    28. });
    29. }
    30. doIt();
    31. // async await方式
    32. async function doIt() {
    33. console.time("doIt");
    34. const time1 = 300;
    35. const time2 = await step1(time1);
    36. const time3 = await step2(time2);
    37. const result = await step3(time3);
    38. console.log(`result is ${result}`);
    39. console.timeEnd("doIt");
    40. }
    41. doIt();

    2、可以对Promise进行并行处理

    1. console.time('total time')
    2. await Promise.all([
    3. (async()=>console.log('输出结果:',await waitFun(3000)))(),
    4. (async()=>console.log('输出结果:',await waitFun(2000)))(),
    5. (async()=>console.log('输出结果:',await waitFun(1000)))(),
    6. ]);
    7. console.timeEnd('total time')
    8. /**
    9. * 输出结果: 1000
    10. * fn3 time: 1009 ms
    11. *
    12. * 输出结果: 2000
    13. * fn2 time: 2010 ms
    14. *
    15. * 输出结果: 3000
    16. * fn1 time: 3011 ms
    17. *
    18. * total time: 3011 ms
    19. */

  • 相关阅读:
    如何理解UML2.5.1(02篇)
    记录--uni-app实现蓝牙打印小票
    【无标题】Angular/Material
    enum, sizeof, typedef
    股票交易路上的一点感悟
    机器学习笔记之支持向量机(一)模型构建思路
    TiDB 集群中能够采集的诊断数据类型
    C#IP转int int转IP
    74.搜索二维矩阵
    分布式事务基础理论
  • 原文地址:https://blog.csdn.net/weixin_45776308/article/details/126245771