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,到此结束,后续会把实际应用场景更新进来,欢迎指出毛病哦!

 

6.补充:
            处理错误逻辑
    ps:示例6-1-1。
            (一): try/catch/finally
                如果try块中的任何代码发生了错误,就会立即退出代码执行过程,然后接着执行catch块,此时,catch块会接收到一个包含错误信息的对象。
                finally子句一经使用,其代码无论如何都会执行。
                只要代码中包含finally子句,则无论try或catch语句块中包含什么样的代码——甚至return语句,都不会阻止finally子句的执行。
                执行顺序try->catch->finally。
            (二):JavaScript throw 语句:
                Throw抛出一个错误。
                创建自定义错误。
                可抛出字符串,数字,逻辑值或对象。
                !!!!!抛出错误javascript会停止往下执行。
                ps: throw “ too bing”
                throw 500
                throw new Error(‘’这是一个错误!!!);
            (三):函数定义方式
                (1):函数声明
                    function fun (a,b){
                        return a*b;
                    }
                    fun(1,2);
                    不会立即执行。
                (2):函数表达式
                    let a = function(a,b){
                        return a*b;
                    }
                    a(1,2);
                    等同于匿名函数通过变量名调用。
                (3):Function()构造函数
                    let fun = new Function('a','b','return a*b');
                    fun(1,2);
                (4):函数提升
                    提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为。
                    提升(Hoisting)应用在变量的声明与函数的声明。
                ps:示例6-3-4
                (5):函数执行顺序
                ps:示例6-3-5
                (6):作用域
                ps:示例6-3-6

  

 

 1 let fun = async function (type) {
 2         if (type) {
 3             return '示例6-1-1';
 4         } else {
 5             throw new Error('sorry is Error!!!')
 6         }
 7     }
 8     async function test() {
 9         try {
10             let a = await fun(false);
11             console.log(a)
12         } catch (err) {
13             console.log(err);
14             return;
15         } finally {
16             console.log('我执行了!!!')
17         }
18     }
19     test();
 1 /*示例6-3-4*/
 2     function fun(a, b) {
 3         return a * b;
 4     }
 5     console.log(fun(1, 2), '函数声明');
 6 
 7     let a = function (a, b) {
 8         return a * b;
 9     }
10     console.log(a(1, 2), '函数表达式'); //不能在初始化之前使用
11     let fun1 = new Function('a', 'b', 'return a*b');
12     console.log(fun1(1, 2), '构造函数');
13 
14     /*示例6-3-5*/
15     function f() { return 1; }
16     console.log(f()); // 第四个函数把第一个函数覆盖 4
17 
18     var f = new Function("return 2;");
19     console.log(f()); // 第二个函数把第四个函数覆盖 2
20 
21     var f = function () { return 3; }
22     console.log(f()); // 第三个函数把第二个函数覆盖 3
23 
24     function f() { return 4; }
25     console.log(f()); // 第四个函数已经被覆盖 3
26 
27     var f = new Function("return 5;");
28     console.log(f()); // 第五个函数把第三个函数覆盖 5
29 
30     var f = function () { return 6; }
31     console.log(f()); // 第六个函数把第五个函数覆盖 6
32 
33     /*示例6-3-6*/
34     var k = 4;
35     window.onload = function () {
36 
37         var k = 1;
38 
39         function t1() {
40             var k = 2;
41 
42             function test() {
43                 return k;
44             }
45             console.info(test()); // 弹出 2
46 
47             var test = function () {
48                 return k;
49             };
50             console.info(test()); // 弹出 2
51 
52             var test = new Function("return k;"); // 每次执行的时候,动态的new,顶级作用域,无法获得局部变量
53             console.info(test()); // 弹出 4
54 
55         }
56         t1();
57     };
原文地址:https://www.cnblogs.com/yushihao/p/14961214.html