zoukankan      html  css  js  c++  java
  • 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肯不是同步关系,要想同步必须在一个函数。
     
    至此已经结束了。当然还有其他解决方案 有时间接着整理

      

  • 相关阅读:
    笔试-2020软件工程师Java(上海)中科创达(收获很多,自己基础还是不行)
    SpringCloud-Spring Cloud 2 Finchley.M9报错问题
    IDEA 实体类生成serialVersionUID
    idea创建maven项目时出现Unable to import maven project: See logs for details
    Eclipse可以执行jsp文件却无法访问Tomcat主页
    已知n个正数:wi, 1<=i<=n, 和M。要求找出{wi }的所有子集使得子集内元素之和等于M。例如: n=4, (w1,w2,w3,w4)=(11,13,24,7),M=31 则满足要求的子集是(11,13,7)和(24,7)。
    嵌入式系统外部中断实验(按下按键,LED灯依次熄灭)
    嵌入式系统按键实现(按下按钮,LED灯熄灭)
    如何跳转一个由两个框架组成的页面
    对某个页面的过滤
  • 原文地址:https://www.cnblogs.com/zshno1/p/15710348.html
Copyright © 2011-2022 走看看