foreach的異步(async,await)的問題及其處理方式


開發中遇見個難題很苦惱,好在我解決了,只要能解決我就很開心😄😄😄

本篇文章從forEach方法 到promise 到async await統統理解個遍,進入正題

 

先看下面代碼會出現什么問題:

     const arr = [1,2,3,4,5,6];
        const result = [];
        const fn = (item) => {
            let time = Math.ceil(Math.random()*1000)
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve(item)
                }, time);
            })
        }
        arr.forEach(async (item) => {
            const val = await fn(item);
            result.push(val);
            console.log(result);
        })
       

 輸出結果順序,看隨機數的臉色。 可能是[6, 5, 4, 1, 3, 2] 或者 [3, 5, 4, 6, 1, 2] 或者等等。。。。。。。

 那么問題來了
 問題1: 我想在這個forEach執行完之后怎么按arr的順序得到結果
 問題2: 怎么等所有異步執行完成拿到result,再執行以后的代碼。
 今天就伴隨這倆問題我們開始整
        const result1 = [];
        (async()=>{
            for(let i = 0; i < arr.length; i++){
                const val1 = await fn(arr[i]);
                result1.push(val1);
            }
            //在這里拿到執行結果result,再執行依賴result的代碼
            console.log(result1);
        })();    

 這個結果妥妥的解決了,得到的順序是 [1, 2, 3, 4, 5, 6],知道為啥嗎?你要知道那你可以走了 拜拜👋

 接着來, 我們不是未來解決問題而解決問題。接下來就要搞清楚forEach為啥不行
 
 看下forEach的實現源碼:
 
     // Production steps of ECMA-262, Edition 5, 15.4.4.18
        // Reference: http://es5.github.io/#x15.4.4.18
        if (!Array.prototype.forEach) {

        Array.prototype.forEach = function(callback, thisArg) {

            var T, k;

            if (this == null) {
            throw new TypeError(' this is null or not defined');
            }

            // 1. Let O be the result of calling toObject() passing the
            // |this| value as the argument.
            var O = Object(this);

            // 2. Let lenValue be the result of calling the Get() internal
            // method of O with the argument "length".
            // 3. Let len be toUint32(lenValue).
            var len = O.length >>> 0;

            // 4. If isCallable(callback) is false, throw a TypeError exception.
            // See: http://es5.github.com/#x9.11
            if (typeof callback !== "function") {
            throw new TypeError(callback + ' is not a function');
            }

            // 5. If thisArg was supplied, let T be thisArg; else let
            // T be undefined.
            if (arguments.length > 1) {
            T = thisArg;
            }

            // 6. Let k be 0
            k = 0;

            // 7. Repeat, while k < len
            while (k < len) {

            var kValue;

            // a. Let Pk be ToString(k).
            //    This is implicit for LHS operands of the in operator
            // b. Let kPresent be the result of calling the HasProperty
            //    internal method of O with argument Pk.
            //    This step can be combined with c
            // c. If kPresent is true, then
            if (k in O) {

                // i. Let kValue be the result of calling the Get internal
                // method of O with argument Pk.
                kValue = O[k];

                // ii. Call the Call internal method of callback with T as
                // the this value and argument list containing kValue, k, and O.
                callback.call(T, kValue, k, O);
            }
            // d. Increase k by 1.
            k++;
            }
            // 8. return undefined
        };
        }

 

看完你會發現:

forEach每次執行都會執行一個回調函數,是不是聽不大明白,舉個例子
            async function fn2 (){
                let val2 = await fn(1);
                console.log(val2)
            };
            
            async function fn3 (){
                let val3 = await fn(2);
                console.log(val3)
            };
            fn2();
            fn3();        
forEach的回調函數就好比這樣,這個很容易看懂fn2和fn3肯不是同步關系,要想同步必須在一個函數。
 
至此已經結束了。當然還有其他解決方案 有時間接着整理

 

 

  


免責聲明!

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



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