大学生涯vueVue学习笔记(九)
Jieasync 与 await
1. async
- async 作为一个关键字放到声明函数前面,表示该函数为一个异步任务,不会阻塞后面函数的执行
- async 函数里如果有异步过程会等待,但async 函数本身会马上返回,不会阻塞当前线程。可以简单认为 async 函数工作在主线程,同步执行,不会阻塞界面渲染;async 函数内部由 await 修饰的异步过程,工作在相应的协程上,会阻塞等待异步任务的完成再返回
- async 函数返回类型为 Promise 对象
async 函数会返回一个 promise,并且 Promise 对象的状态值是 resolved(成功的)
如果没有在 async 函数中写 return,那么 Promise 对象 resolve 的值就是是 undefined
如果写了 return,那么 return 的值就会作为成功的时候传入的值
这是和普通函数本质上不同的地方,也是使用时重点注意的地方: 1. return new Promise(),这个符合 async 函数本意 2. return data 这是同步函数的写法,特别注意这其实就相当于 Promise.resolve(data);还是一个 Promise 对象,但在调用 async 函数的地方通过简单的等号操作(=)是拿不到这个 data 的,因为返回值是一个 Promise 对象,所以需要用 then(data => { })才可以拿到 data 3. 如果没有返回值,相当于返回了 Promise.resolve(undefined);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <script> const aa = async () => { return 1; };
const bb = async () => { return Promise.resolve(1); };
console.log(`output->aa()`, aa()); aa().then((res) => { console.log(`output->res`, res); }); </script>
|
- 无等待
在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且不会阻塞后面的语句,这和普通返回 Promise 对象的函数并无二致
2. await
- await 只能在 async 函数内部使用:不能放在普通函数里面,否则会报错
- await 关键字后面跟 Promise 对象:在 Pending 状态时,相应的协程会交出控制权,进入等待状态,这是协程的本质
- await 是 async wait 的意思: wait 的是 resolve(data)的消息,并把数据 data 返回,比如下面代码中,当 Promise 对象由 Pending 变为 Resolved 的时候,变量 a 就等于 data,然后再顺序执行下面的语句 console.log(a),这真的是等待,真的是顺序执行,表现和同步代码几乎一模一样
1 2 3 4 5
| const a = await new Promise((resolve, reject) => { return resolve(data); }); console.log(a);
|
- await 后面也可以跟同步代码: 不过系统会自动将其转化成一个 Promsie 对象
1 2 3 4 5
| const a = await "hello world";
const a = await Promise.resolve("hello world");
const a = "hello world";
|
- await 对于失败消息的处理: await 只关心异步过程成功的消息 resolve(data),拿到相应的数据 data,至于失败消息 reject(error),不关心不处理;对于错误的处理有以下几种方法供选择:
- 让 await 后面的 Promise 对象自己 catch
- 也可以让外面的 async 函数返回的 Promise 对象统一 catch
- 像同步代码一样,放在一个 try…catch 结构中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| async function fetchData() { try { const array = null; let data = await asyncFn(); if (array.length > 0) { array.push(data); } } catch (error) { console.log(error); } }
document.addEventListener("DOMContentLoaded", fetchData);
|
- await 对于结果的处理: await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西,如果它等到的不是一个 Promise 对象,那么 await 表达式的运算结果就是它等到的东西;如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞其后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果;虽然是阻塞,但 async 函数调用并不会造成阻塞,它内部所有的阻塞都被封装在一个 Promise 对象中异步执行,这也正是 await 必须用在 async 函数中的原因
3. 综合案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| <script> const myPromise1 = () => { return new Promise((resolve, reject) => { console.log(`output->创建myPromise1`); setTimeout(() => { const random = Math.random(); if (random > 0.5) { resolve(`myPromise1成功`); } else { reject(`myPromise1失败`); } }, 2000); }); }; const myPromise2 = () => { return new Promise((resolve, reject) => { console.log(`output->创建myPromise2`); setTimeout(() => { const random = Math.random(); if (random > 0.5) { resolve(`myPromise2成功`); } else { reject(`myPromise2失败`); } }, 2000); }); }; const myPromise3 = () => { return new Promise((resolve, reject) => { console.log(`output->创建myPromise3`); setTimeout(() => { const random = Math.random(); if (random > 0.5) { resolve(`myPromise3成功`); } else { reject(`myPromise3失败`); } }, 2000); }); }; const myAsync = async () => { try { console.log(`myAsync开始执行`); const data1 = await myPromise1(); const data2 = await myPromise2(); const data3 = await myPromise3(); return `myAsync执行成功`; } catch (error) { console.log(`myAsync执行出错:`, error); } }; myAsync() .then((res) => { console.log(`output->res`, res); }) .catch((error) => { console.log(`output->error`, error); }); </script>
|