中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中Promise如何處理異步的并行與串行

發布時間:2022-12-28 15:58:49 來源:億速云 閱讀:120 作者:iii 欄目:開發技術

這篇“JavaScript中Promise如何處理異步的并行與串行”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“JavaScript中Promise如何處理異步的并行與串行”文章吧。

    一、異步的“并行”

    同時處理,相互之間沒啥依賴

    // 執行FN1返回一個promise實例,實例中管理了一個異步編程的代碼,當定時器到時間后,才會把實例的狀態改為成功
    const fn1 = () => {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(1);
            }, 1000);
        });
    };
    const fn2 = () => {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(2);
            }, 2000);
        });
    };
    const fn3 = () => {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(3);
            }, 3000);
        });
    }; 
    
    
    // 異步的“并行”:同時處理,相互之間沒啥依賴
    fn1().then(result => {
        console.log(result);
    });
    fn2().then(result => {
        console.log(result);
    });
    fn3().then(result => {
        console.log(result);
    });

     并行中的綜合處理

    一起發送多個請求(處理多個異步),但是需要等到所有異步都成功,我們再整體做啥事!!

    • 語法:let promise = Promise.all([promise1,promise2,...]);

    • 執行Promise.all返回一個新的promise實例 @P

      • 并且傳遞一個數組,數組中包含N多其它的promise實例

      •  如果數組中的每一個promise實例最后都是成功的,則@P也將會是成功的,它的值也是一個數組,按照順序依次存儲各個promise實例的結果;但凡數組中的某個promsie實例是失敗的,則@P也是失敗的,值是當前這個實例失敗的原因!

      •  如果數組中有一項并不是promise實例(例如:是個100),則瀏覽器也會把其默認變為一個狀態是成功的promsie實例,值就是當前項本身

    let p = Promise.all([Promise.resolve(100), fn1(), 200, fn3(), fn2()]); //瀏覽器默認會把200 變為一個成功的promsie實例
    p.then(results => {
        console.log(`成功:${results}`); // 成功:100,1,200,3,2 順序和最開始是一致的,不會考慮誰先成功
    }).catch(reason => {
        console.log(`失敗:${reason}`);
    }); 
    
    //new Error('xxx')不是promise實例=》Promise.resolve(new Error('xxx')) 值是Error對象
    let p = Promise.all([Promise.resolve(100), fn1(), new Error('xxx'), Promise.reject(200), fn3(), fn2()]);
    p.then(results => {
        console.log(`成功:${results}`);
    }).catch(reason => {
        console.log(`失敗:${reason}`); //失敗:200 遇到錯誤直接返回
    }); 
    
    //=>等三個異步都成功做什么事情 所用時間3s
    Promise.all([fn1(), fn2(), fn3()]).then(results => {
        console.log(`三個異步都成功了,分別的結果:${results}`);
    });

    二、異步的“串行”:

    第一個異步成功才能發送第二個,第二個成功才能發送第三個....多個異步之間一般是有依賴的

    2.1 then鏈機制處理

    promise狀態是失敗,如果不用catch(或者onrejected)處理,控制臺會拋出異常:Uncaught (in promise) xxx,但是此異常不會阻礙下面代碼執行!!

    fn1().then(result => {
        console.log(`第一個成功:${result}`);
        return fn2();
    }).then(result => {
        console.log(`第二個成功:${result}`);
        return fn3();
    }).then(result => {
        console.log(`第三個成功:${result}`);
    }).catch(reason => {
        console.log(`只要其中一個失敗,直接順延到這里,其余剩下的請求就不發送了!`);
    });

    2.2 真實項目中,想實現異步的串行,我們一般使用async+await

    (async function () {
        let result = await fn1();
        console.log(`第一個成功:${result}`);
    
        result = await fn2();
        console.log(`第二個成功:${result}`);
    
        result = await fn3();
        console.log(`第三個成功:${result}`);
    })();

    2.3 promise.then(onfulfilled,onrejected) 在內存中的執行

    首先,我們復習一下事件循環機制 EventLoop

    • 同步代碼執行,遇到一個異步任務

      • 1. 先把其放在 WebAPI 進行監聽

      • 2. 當前異步任務監聽到可以執行了,則再把其放在EventQueue中,排隊等待執行

    • 同步任務執行完,主線程空閑下來

      •  1. 去EventQueue中找可執行的微任務,如果微任務中都執行完了,再去找可執行的宏任務「隊列:優先級隊列 & 先進先出」

      • 2. 取到的任務都放在Stack中交給主線程去執行

      •  ......

    那么接下來我們來了解一下promise.then(onfulfilled,onrejected) 在內存中的執行

    promise.then(onfulfilled,onrejected) 在內存中的執行

    • 情況一:我此時已經知道promise是成功還是失敗的

      •  我們此時應該去執行onfulfilled或者onrejected,但是不是立即執行,它是一個異步的微任務

      • 首先把執行對應的方法這個事情放在WebAPI中監聽,但是因為此時已經知道狀態了,對應的方法肯定可以執行,所以緊接著把它挪至到EventQueue中「異步微任務隊列」等待執行

    • 情況二:此時的promise還是pending狀態

      •  我們把onfulfilled/onrejected先存儲起來,只有當后面,我們把實例的狀態修改為成功/失敗的時候,再取出之前存儲的方法,把其執行「而且此時再執行,還是個異步微任務」

      • 還是要經歷:WebAPI -> EventQueue

    三、aysnc修飾符

    aysnc最主要的作用就是:如果想在函數中使用await,則當前函數必須基于async修飾

    aysnc修飾符,讓函數的返回值成為一個promise實例 這樣就可以基于THEN鏈去處理了

    • 如果函數自己本身就返回一個promise實例,則以自己返回的為主

    • 如果函數自己本身沒有返回promise,則會把返回值變為一個promise實例:狀態=> 成功 值=>返回值

    • 如果函數執行報錯則返回的實例狀態是失敗,值是報錯原因,但不影響下面代碼執行

    async function fn() {
        return 10;
    }
    fn().then(result => {
        console.log(result);//輸出10
    }); 
    
    async function fn() {
        return async function () {
            return 10;
        };
    }
    fn().then(result => {
        // result:async function () {...}  函數
        return result();
    }).then(result => {
        console.log(result); //10
    });

    四、await:等待

    • 我們一般在其后面放promise實例 它會等待實例狀態為成功,再去執行“當前上下文”中 ,await下面的代碼

    【如果promise實例管控的是一個異步編程,其實它是在等待異步成功,再執行下面的代碼,類似于把異步改為同步的效果】

    • await 10 =>默認轉為 await Promise.resolve(10)

      • 如果后面放的不是promise實例,則瀏覽器默認把其轉換為”狀態為成功,值就是這個值 " 的實例

    const fn1 = () => {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(1);
            }, 1000);
        });
    };
    (async function () {
        let result = await fn1();
        console.log(result); 
      //下面代碼可以執行,說明await后面的promise實例,它的狀態已經是成功了,await的返回值就是當前promise實例的值
        console.log('OK');
    })(); 
    
    
    //=======================如果await后面的promise實例狀態是失敗的
    const fn1 = () => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                reject(0);
            }, 1000);
        });
    };
    (async function () {
        let result = await fn1(); //如果await后面的promise實例狀態是失敗的,則下面代碼永遠都不會執行了
        console.log(result);
        console.log('OK');//如果是失敗的則這句話不會執行
    })();
    
    //===================================================
    (async function () {
        let a = await 10; //->Promise.resolve(10)
        console.log(a); //10
        let b = await Promise.resolve(20);
        console.log(b); //20
        try {
            let c = await Promise.reject(30); //Uncaught (in promise) 30
            console.log(c);
        } catch (err) {
            console.log(err); //30
        }
        console.log('OK'); //'OK'
    })();

    await中的異步

    await中的異步:當前上下文,await下面的代碼執行是異步微任務

    • 情況1:await后面的promise實例我們已知是成功的

      先把微任務放置在WebAPI中,但是知道是可以執行的,則直接在挪至到EventQueue中等待執行

    • 情況2:await后面的promise實例還是pending狀態

        此時我們把微任務放置在WebAPI中監聽,等到后期promise實例是成功態后,再把它挪至到EventQueue中等待執行即可 

    (async function () {
        let b = await Promise.resolve(20);
        console.log(b);
    })()

    五、思考題

    思考題1

    console.log(1);
    setTimeout(() => { console.log(2); });//宏1
    console.log(3);
    let p1 = new Promise(resolve => {//new Promise 立即會把executor函數執行 是同步
        console.log(4);
        resolve('A'); //執行resolve P1的狀態是成功=》已知
        console.log(5);
    });
    console.log(6);
    p1.then(result => {//.then是異步 已知狀態 放進WebAPI中監聽 但是因為是已知狀態 方法肯定執行 則從WebAPI監聽隊列挪到EventQueue中等待
        console.log(result); //微1
    });
    console.log(7);
    let p2 = new Promise(resolve => { //立即執行executor函數 setTimeout是異步則會放進WebAPI監聽 宏2
        setTimeout(() => {
            resolve('B');
            console.log(10); //執行宏2=>@1 更改了p2的狀態 @2之前存儲的.then方法執行
        });
    });
    console.log(8);
    p2.then(result => {//p2的狀態是未知則會先存起來
        console.log(result);
    });
    console.log(9);
    思路及圖解

    JavaScript中Promise如何處理異步的并行與串行

    思考題2

    基于事件綁定屬于異步宏任務

    let body = document.body;
    body.addEventListener('click', function () {
        Promise.resolve().then(() => {
            console.log(1);
        });
        console.log(2);
    });
    body.addEventListener('click', function () {
        Promise.resolve().then(() => {
            console.log(3);
        });
        console.log(4);
    });
    思路及圖解

    JavaScript中Promise如何處理異步的并行與串行

    思考題3

     async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    async function async2() {
        console.log('async2');
    }
    console.log('script start');
    setTimeout(function () {
        console.log('setTimeout');
    }, 0)
    async1();
    new Promise(function (resolve) {
        console.log('promise1');
        resolve();
    }).then(function () {
        console.log('promise2');
    });
    console.log('script end');

    思路及圖解

    JavaScript中Promise如何處理異步的并行與串行

    以上就是關于“JavaScript中Promise如何處理異步的并行與串行”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    招远市| 鸡泽县| 婺源县| 尤溪县| 兴义市| 修文县| 荔浦县| 临邑县| 乌海市| 大邑县| 无为县| 高台县| 普陀区| 油尖旺区| 永春县| 中卫市| 镇赉县| 石林| 龙游县| 宜昌市| 镇安县| 五家渠市| 通榆县| 嵩明县| 越西县| 乌恰县| 慈利县| 孝感市| 镇雄县| 宣武区| 探索| 察哈| 丽江市| 莱芜市| 石家庄市| 嫩江县| 湟中县| 双流县| 凤城市| 靖州| 嘉兴市|