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     };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM