async 函数是使用async
关键字声明的函数。 async 函数是AsyncFunction构造函数的实例, 并且其中允许使用await
关键字。async
和await
关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
。(MDN介绍)
被async修饰的函数会返回一个promise对象,如:
- async function fn1() {
- return 2
- }
-
- const res = fn1()
- console.log(res);
- //output:
- //promise{
:2}
这里可以看到,fn1返回了一个fulfilled(resolved)的promise对象,且结果值为2。实际上,这里返回的primose状态的规则,可以参考上一节笔记中问题三中的规则,两者是一样的。比如,我在async函数中抛出一个异常,那么函数返回的promise状态就是rejected且结果值为你throw的东西:
- async function fn1() {
- throw new Error('jesus')
- }
-
- const res = fn1()
- console.log(res);
- //output:
- //Promise {
: Error: jesus
那么,async函数是同步还是异步执行的呢?我们写个代码来验证一下:
- let a = 1
-
- async function fn1() {
- a = 2
- }
- fn1()
-
- console.log('a:',a);
- //output:
- //a: 2
事实证明,async函数是同步执行的,至少目前来看是。
await
操作符用于等待一个Promise 对象。它只能在异步函数 async函数中使用。(MDN介绍)基本示例:
- function fn1() {
- return Promise.resolve(6)
- }
-
- async function fn2() {
- const val = await fn1()
- console.log(val);
- }
- fn2()
- //output:6
await返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。例如:
- function fn1() {
- return 6
- }
-
- async function fn2() {
- const val = await fn1()
- console.log(val);
- }
- fn2()
- //output:6
如果Promise对象的处理结果是失败的,那么需要用try...catch进行捕获。例如:
- function fn1() {
- return Promise.reject(123)
- }
-
- async function fn2() {
- try {
- const val = await fn1()
- console.log(val);
- } catch (error) {
- console.error(error);
- }
- }
- fn2()
- //output:123
await是否会等待Promise对象中的任务执行完?
会的。看下例代码
- async function fn2() {
- try {
- const val = await new Promise((resolve, reject) => {
- setTimeout(() => {
- console.log("执行异步任务一");
- resolve("data1");
- }, 1000);
- }).then((val) => {
- console.log("任务一结果:", val);
- console.log("执行同步任务二");
- return "data2";
- });
- console.log("最终结果:", val);
- } catch (error) {
- console.error(error);
- }
- }
- fn2();
- //output:
- //执行异步任务一
- //任务一结果: data1
- //执行同步任务二
- //最终结果: data2
问题八讲的是,如何让promise中的异步任务的结果同步到主线程中。那么在知道了await可以等待promise执行完毕并取出中的值后,我们便可以利用async/await来解决同步到主线程的问题。先看下原来的代码
- let a = 1
- new Promise((resolve,reject)=>{
- setTimeout(() => {
- a = 2
- resolve(a)
- }, 1000);
- })
- .then(val=>{
- console.log('a in then:',val); //为了方便区别哪里的a,加点输出文字
- })
- console.log('a in main:',a);
- //output:
- //a in main: 1
- //a in then: 2
我们只需要对new Promise封装一下即可,如下所示:
- let a = 1;
-
- async function changeA() {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- a = 2;
- resolve(a);
- }, 1000);
- });
- }
-
- await changeA();
-
- console.log("a in main:", a);
- //output: a in main: 2
但是需要注意的是,如果你是在html文件的script标签里运行这段代码,是会报错的,我们需要给script标签加上type="module"的属性描述即可。