1. 程式人生 > 實用技巧 >promise,與async函式

promise,與async函式

一、Promise

1.1回顧回撥函式:

1.概念:

一個函式在另一個函式呼叫(一個函式傳遞另一個函式做引數使用)

2.非同步和同步:

js,在主執行緒上面,先執行同步任務,再執行非同步任務,等主執行緒上的同步任務全部完成之後,回到非同步佇列進行查詢,將非同步佇列裡面的任務放到執行棧中,繼續遵循規則;

同步:排隊執行;

非同步:不會阻塞後面程式碼執行;

1.2 promise

1)概念: 解決非同步程式設計的方法

2)語法: 需要new 例項化;resolve返回的是成功狀態值;reject返回的是失敗狀態值;

接收失敗狀態的區別:

1. catch直接捕獲reject返回的失敗狀態值;

2.then裡面有第二個引數err,捕獲就是失敗狀態值;

區別:使用catch,不僅可以接收reject返回的失敗狀態值,也可以捕獲在成功狀態時,處理業務邏輯時報的錯;then裡面的第二個回撥函式來接收;只能捕獲reject返回的失敗狀態的值

3)特點:

1. 三種狀態:進行時,已成功,已失敗

2. 兩種狀態轉換:進行時=》已成功;進行時=》已失敗

4promise一旦建立就會立即執行(同步任務);

呼叫resolvereject執行非同步任務;狀態也會發生改變:由進行中=》已成功或者是已失敗;

      console.log(1);

        let p1 = new
Promise((resolve, reject) => { console.log('promise'); // 同步任務 進行中 resolve("success"); }); p1.then(res => { console.log(res) // 非同步任務 微任務 }); console.log(2); // 最終打印出的結果先後順序為 1, promise, 2, success

5)鏈式呼叫:從第二個then開始,拿的是上一個
then return之後的返回值;

案例1

      function fn(num) {

            return new Promise(resolve => {

                setTimeout(() => {

                    resolve(num)

                }, 1000);

            });

        };

        console.log(fn());

        fn(10).then(res => {

            console.log(res)

            return fn(++res)

        }).then(res => {

            console.log(res)

            return fn(++res)

        }).then(res => {

            console.log(res)

        });

6)解決回撥地獄:

ajax請求成功與失敗結果與promise本身的成功與失敗的狀態沒有必然的聯絡

      function myAjax({

            type = "get",

            url,

            data = {}

        }) {

            return new Promise((resolve, reject) => {

                $.ajax({

                    type,

                    url,

                    data,

                    success: function(response) {

                        resolve(response.result.data);

                    }

                })

            });

        };

7)Promise.all Promise.race

Promise.all() 做併發處理,等所有的請求有了返回值之後,同一返回,返回的是一個數組;

Promise.race() 獲取的是請求速度最快的值;(設定定請求時間,超過500ms的時候,提示使用者請求超時。)

        let p1 = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('123');
            },5000);
        });
        let p2 = new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('456');
                // reject('error');
            },1000);
        }).catch(err=>{
            console.log(err);
        }) ;
        Promise.all([p1,p2]).then(res=>{
            console.log(res);     //  ["123", "456"]  等5s後才會打印出
        });
        Promise.race([p1,p2]).then(res=>{
            console.log(res);     //   456 
        });        

錯誤捕獲兩種方法

直接在all方法後面直接寫catch;只返回失敗狀態值,其他請求成功狀態的值,無法返回;

誰返回的失敗狀態,誰來處理;既可以接收本身自己的失敗狀態值,其他請求成功狀態的值,也不受影響

二、async函式:

1.Async 函式是Generator函式語法糖;

2.語法:

1)function前面加async關鍵字;

箭頭函式async關鍵字放在形參的前面;

2)返回的是一個promise物件;

3)await 等待:

  1.await後面的值,不會返回到函式的外部;

  2.async函式內可以有多個await

  3.await等待的是後面表示式的結果值;注意,如果是promise物件,預設情況下只返回成功狀態值;

  4.await有阻塞後面程式碼執行作用,await後面的表示式有結果之後,下面的程式碼才可以執行;

  5.async函式內部是同步任務;不影響主執行緒上任務的執行順序;

   let p1 = new Promise(resolve => {

            setTimeout(() => {

                resolve("p1")

            }, 3000);

        });

        console.log("fn start");

        async function fn() {

            console.log(1);

            let a = await p1;

            console.log(a);

            console.log(2);

        };

        console.log("fn end");

        fn();

4)捕獲錯誤資訊:

  1. 直接使用catch
  2. Try...catch
  3. 優雅封裝方法:
       let p1 = new Promise((resolve, reject) => {
            if (true) {
                resolve("success")
            } else {
                reject("失敗")
            };
        });

        // promise自己呼叫catch方法
        // async function fn() {
        //     let a = await p1.catch(err => {
        //         console.log(err)
        //     });
        //     console.log(a);
        // };
        // fn();

        // try...catch
        // async function fn() {
        //     try {
        //         let a = await p1;
        //         console.log(a)
        //     } catch (error) {
        //         console.log(error)
        //     };
        // };
        // fn();

        // 優雅捕獲錯誤
        function to(promise) {
            return promise.then(res => [null, res]).catch(err => [err,undefined]);
        };

        async function fn() {
            let [err, data] = await to(p1);
            console.log(err, data);
        };

        fn();

5)解決回撥地獄:

案例11秒列印一個1

     function fn2() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(1);
                }, 1000);
            })
        }
        async function fn3() {
            let a = await fn2();
            console.log(a);
            let b = await fn2();
            console.log(b);
            let c = await fn2();
            console.log(c);
            let d = await fn2();
            console.log(d);
        }
        fn3();

案例2ajax封裝

   function myAjax({

            type = "get",

            url,

            data = {}

        }) {

            return new Promise(resolve => {

                $.ajax({

                    type,

                    url,

                    data,

                    dataType: "jsonp",

                    success: function(response) {

                        resolve(response);

                    }

                })

            });

        };