异步编程async/await

本文详细解析了async/await在JavaScript中的使用,包括异步函数的定义、返回值处理、await关键字的执行机制以及await与async配合实现的同步执行效果。通过实例分析,展示了如何控制异步函数的执行顺序和理解await的阻塞与非阻塞特性。
摘要由CSDN通过智能技术生成

async/await

使用 async 关键字可以让函数具有异步特征,但总体上其代码仍然是同步求值的。

async function foo() {
	console.log(1);
}

foo();
console.log(2);

异步函数如果使用 return 关键字返回了值(如果没有 return 则会返回 undefined),这个值会被 Promise.resolve()包装成一个Promise对象。

:异步函数始终返回Promise对象!!

async function foo() {
	console.log(1);
	return 3;
}
// 给返回的Promise添加一个解决处理程序
foo().then(console.log);
console.log(2);
// 1
// 2
// 3

//等同于
async function foo() {
	console.log(1);
	return Promise.resolve(3);
}
// 给返回的Promise添加一个解决处理程序
foo().then(console.log);
console.log(2);
// 1
// 2
// 3

await

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

await关键字会暂停执行异步函数之后的代码,使其让出 JavaScript 运行时的执行线程,先执行异步。

  1. async 单独使用的时候,放在函数前面表示这个函数是一个异步函数,如果 async 函数有返回结果,必须要用.then()方法来承接(也就是返回的值会被自动处理成 promise 对象)

    async function helloAsync(){
        return "helloAsync";
      }
      
    console.log(helloAsync())  // Promise {<resolved>: "helloAsync"}
     
    helloAsync().then(v=>{
       console.log(v);         // helloAsync
    })
    
  2. async await 搭配使用的时候,await 是等待此函数执行后,再执行下一个,可以把异步函数变成同步来执行,控制函数的执行顺序。

    • await 后跟的函数是返回的 promise

      let foo = () => {
        return new Promise(resolve => {
          setTimeout(() => {
            console.log('lee');
            resolve();
          }, 1000);
        });
      };
      
      async function bar() {
        await foo();		
        console.log('van');
      }
      console.log(bar()); // 隔1秒同时输出 lee van
      
    • await 后跟的是普通函数(非 promise()

      let f1 = () => {
        setTimeout(() => {
          console.log('lee');
        }, 1000);
      };
      
      let f2 = () => {
        setTimeout(() => {
          console.log('van');
        }, 1000);
      };
      
      async function bar() {
        await f1();
        await f2();
        console.log('yeah');
      }
      
      console.log(bar()); // yeah 隔1秒同时输出 lee fan
      
  • 如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
  • 如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西;
  1. await 一定要搭配 async 使用,如果在 async function 函数体外使用 await ,你只会得到一个语法错误。

注意:

  1. await 关键字必须在异步函数中使用,不能在顶级上下文如<script>标签或模块中使用
  2. await 关键字也只能直接出现在异步函数的定义中,在同步函数内部使用 await 会抛出 SyntaxError
  3. await 不允许出现在箭头函数中
  4. 异步函数如果不包含 await 关键字,其执行基本上跟普通函数没有什么区别
  5. JavaScript 运行时在碰到 await 关键字时,会记录在哪里暂停执行。等到 await 右边的值可用了,JavaScript 运行时会向消息队列中推送一个任务,这个任务会恢复异步函数的执行

实例分析await执行顺序:

async function foo() {
	console.log(2);
	console.log(await Promise.resolve(8));
	console.log(9);
}
async function bar() {
 	console.log(4);
	console.log(await 6);
	console.log(7);
}
console.log(1);
foo();
console.log(3);
bar();
console.log(5);  

// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
  1. 打印 1;
  2. 调用异步函数 foo()
  3. (在 foo()中)打印 2;
  4. (在 foo()中)await 关键字暂停执行,向消息队列中添加一个 Promise在落定之后执行的任务;
  5. Promise立即落定,把给 await 提供值的任务添加到消息队列;
  6. foo()退出;
  7. 打印 3;
  8. 调用异步函数 bar()
  9. (在 bar()中)打印 4;
  10. (在 bar()中)await 关键字暂停执行,为立即可用的值 6 向消息队列中添加一个任务;
  11. bar()退出;
  12. 打印 5;
  13. 顶级线程执行完毕;
  14. JavaScript 运行时从消息队列中取出解决 await Promise的处理程序,并将解决的值 8 提供给它;
  15. JavaScript 运行时向消息队列中添加一个恢复执行 foo()函数的任务;
  16. JavaScript 运行时从消息队列中取出恢复执行 bar()的任务及值 6;
  17. (在 bar()中)恢复执行,await 取得值 6;
  18. (在 bar()中)打印 6;
  19. (在 bar()中)打印 7;
  20. bar()返回;
  21. 异步任务完成,JavaScript 从消息队列中取出恢复执行 foo()的任务及值 8;
  22. (在 foo()中)打印 8;
  23. (在 foo()中)打印 9;
  24. foo()返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eynoZzzzc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值