async/await

Posted 前端菜鸡儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了async/await相关的知识,希望对你有一定的参考价值。

async await

我们直接进入主题!!!

 

1.async和await是什么?

        async:
            是ES7语法,用于声明一个function是异步函数。
        await:
            等待一个异步方法完成。
    ps:await只能出现在async函数中,不然会报错,如示例1-1;
        Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
        Await只在异步函数和顶级模块体中有效.

  

 1 /*示例 1-1*/
 2     let fun = function (){
 3         console.log(\'错误示例\');
 4     }
 5     await fun();
 6 
 7     let fun1 = function(){
 8         console.log(\'正确示例\');
 9     }
10     let fun =async function (){
11         await fun1();
12     }
13     fun();
2.async到底干了什么?
       (一):
        我们先看一下async声明的函数,返回值到底是个什么。
    ps:如示例2-1;
        可以看到返回的其实就是一个promise对象。Promise {<fulfilled>: "async"}
        所以,async直接返回一个promise对象。如果在函数中直接return一个直接量,async会通过promise.resolve()封装成promise对象。
    ps:Promise.resolve(e)可以看作是 new Promise(resolve => resplve(e))的简写,可以快速将字面量对象或其他对象分装成promise实例。
        (二):
        使用async不用await可以处理返回值吗?
    ps:如示例2-2-1;
        如示例2-2-2,async声明的函数是一个promise对象,所以我们当然可以用then()链去处理。
        (三):
        到这里就会产生一个疑问,既然async返回是一个promise对象,并且promise的特点就是无等待,在没有await的情况下会立即执行,不会阻塞后面的语句,和普通的promise并无二致,
        我们为什么要用async和await呢?

        我们看示例2-3-1,模拟了一个异步操作,因为promise并不会造成阻塞,所以打印2输出为null,打印1会在一秒以后输出111,
        想一个问题如果我们有的代码是基于异步完成之后的结果,要怎么处理?对,我们可以在then()函数中写,如果有多个promise并且相互依赖呢?

  

 1     /*示例2-1*/
 2 
 3     let fun = async function(){
 4         return \'async\';
 5     }
 6     console.log(fun());//Promise {<fulfilled>: "async"}
 7 
 8     /*示例2-2-1*/
 9     fun().then(e=>{
10         console.log(e);//async
11     })
12 
13     /*示例2-3-1*/
14     var param = null;
15 
16     let fun =  () => {
17         return new Promise(resolve => {
18             setTimeout(() => resolve(function(){
19                 param = \'111\';
20             }), 1000);
21         });
22     }
23 
24     fun().then(v => {
25         v();
26         console.log(param,\'1\');
27     });
28     console.log(param,\'2\');
3.await到底在等什么?
        (一):
        官方介绍,await等待的是一个promise对象或者是其它值。
        实际await等待的是一个返回值,所以await后边可以接普通函数,或者是直接量。
    ps:如示例3-1-1。
        (二):
        await等到了要等的东西,然后呢?
        await是一个运算符,用于组成表达式,await表达式的运算结果取决于等到的东西。
        如果await等到的不是一个promise对象,那await运算结果就是等到的东西。
        如果await等到的是一个promise对象,那会阻塞后面的代码,等着promise对象resolve,然后得到resolve的值,最为await运算结果。
        注意:
            阻塞,只是async把所有的阻塞都封装在一个promise对象中异步执行,这也是await必须使用在async函数中的原因。
    ps:如示例3-2-1。
        示例会先执行打印3 输出null,然后一秒以后异步结束执行1,2。

  

 1     /*示例3-1-1*/
 2     let fun = function () {
 3         return "fun";
 4     }
 5 
 6     let asyncFun = async function () {
 7         return Promise.resolve("asyncFun");
 8     }
 9 
10     async function test() {
11         const v1 = await fun();
12         const v2 = await asyncFun();
13         console.log(v1, v2);
14     }
15 
16     test();
17     /*示例3-2-1*/
18     var param = null;
19 
20     let fun = () => {
21         return new Promise(resolve => {
22             setTimeout(() => resolve(function () {
23                 param = \'111\';
24             }), 1000);
25         });
26     }
27 
28     let awaitFun = async function () {
29         await fun().then(v => {
30             v();
31             console.log(param, \'1\');
32         });
33         console.log(param, \'2\');
34     }
35     awaitFun();
36     console.log(param, \'3\');
4.目前看来使用Promise和async,await好像并没有什么区别?
        (一):
        我们简单做一个比较。
        不用async/await:
    ps:示例4-1-1。
        使用async/await:
    ps:示例4-1-2。
        好,我们发现好像并没有什么区别?so,优势到底在哪里?
        (二):
        async/await优势:
        其实单一的promise并不能发现async/await优势,但是如果处理多个优势就出来了。
        说白了async/await好像就是用来优化promise。
        现在,我们假设一个业务,分成多步,且每一步都依赖于上一步的结果。
    ps:示例4-2-1。
        有没有发现什么???
        在看一个,把业务要求改一下,仍然是三个步骤,但每一个步骤都需要之前每个步骤的结果。
    ps:示例4-2-2。
        哇,是不是很神奇!!!
  1     /*示例4-1-1*/
  2     let fun = function () {
  3         return new Promise(resolve => {
  4             setTimeout(() => resolve("not async/await!!!"), 1000);
  5         });
  6     }
  7 
  8     fun().then(v => {
  9         console.log("async", v);
 10     });
 11     /*示例4-1-2*/
 12     let fun = function () {
 13         return new Promise(resolve => {
 14             setTimeout(() => resolve("is async/await!!!"), 1000);
 15         });
 16     }
 17 
 18     async function test() {
 19         const v = await fun();
 20         console.log(v);
 21     }
 22 
 23     test();
 24 
 25     /*示例4-2-1*/
 26     /**
 27      * 传入参数 n,表示这个函数执行的时间(毫秒)
 28      * 执行的结果是 n + 200,这个值将用于下一步骤
 29      */
 30     function getTime(n) {
 31         return new Promise(resolve => {
 32             setTimeout(() => resolve(n + 200), n);
 33         });
 34     }
 35 
 36     function step1(n) {
 37         console.log(`step1 with ${n}`);
 38         return getTime(n);
 39     }
 40 
 41     function step2(n) {
 42         console.log(`step2 with ${n}`);
 43         return getTime(n);
 44     }
 45 
 46     function step3(n) {
 47         console.log(`step3 with ${n}`);
 48         return getTime(n);
 49     }
 50     /*promise实现*/
 51     function doIt() {
 52         console.time("doIt");
 53         const time1 = 300;
 54         step1(time1)
 55             .then(time2 => step2(time2))
 56             .then(time3 => step3(time3))
 57             .then(result => {
 58                 console.log(`result is ${result}`);
 59                 console.timeEnd("doIt");
 60             });
 61     }
 62 
 63     doIt();
 64     /*async/await实现*/
 65     async function doIt() {
 66         console.time("doIt");
 67         const time1 = 300;
 68         const time2 = await step1(time1);
 69         const time3 = await step2(time2);
 70         const result = await step3(time3);
 71         console.log(`result is ${result}`);
 72         console.timeEnd("doIt");
 73     }
 74 
 75     doIt();
 76 
 77     /*4-2-2*/
 78     function step1(n) {
 79         console.log(`step1 with ${n}`);
 80         return getTime(n);
 81     }
 82 
 83     function step2(m, n) {
 84         console.log(`step2 with ${m} and ${n}`);
 85         return getTime(m + n);
 86     }
 87 
 88     function step3(k, m, n) {
 89         console.log(`step3 with ${k}, ${m} and ${n}`);
 90         return getTime(k + m + n);
 91     }
 92     /*async/await实现*/
 93     async function doIt() {
 94         console.time("doIt");
 95         const time1 = 300;
 96         const time2 = await step1(time1);
 97         const time3 = await step2(time1, time2);
 98         const result = await step3(time1, time2, time3);
 99         console.log(`result is ${result}`);
100         console.timeEnd("doIt");
101     }
102 
103     doIt();
104 
105     /*promise实现*/
106     function doIt() {
107         console.time("doIt");
108         const time1 = 300;
109         step1(time1)
110             .then(time2 => {
111                 return step2(time1, time2)
112                     .then(time3 => [time1, time2, time3]);
113             })
114             .then(times => {
115                 const [time1, time2, time3] = times;
116                 return step3(time1, time2, time3);
117             })
118             .then(result => {
119                 console.log(`result is ${result}`);
120                 console.timeEnd("doIt");
121             });
122     }
123 
124     doIt();
5.总结
        个人理解async/await是用来解决同步异步,更重要的是优化了promise。

ok,到此结束,后续会把实际应用场景更新进来,欢迎指出毛病哦!

  

  

以上是关于async/await的主要内容,如果未能解决你的问题,请参考以下文章

Async/Await替代Promise的理由

promise与async和await的区别

Async/Await是这样简化JavaScript代码的

使用 Async/Await 控制哪些代码停止

如何优雅处理 async await 错误——解读小而美的 awaitjs 库

Gulp/Typescript/Async/Await 代码不起作用 - 为啥?