for循环中嵌套异步请求问题

可直接看第3、4条

1. 产生的问题

//for中嵌套异步时,执行顺序会混乱
function forTest() {
    var start = new Date();
    for (var i=0; i<10; i++) {
        (function(j) {
            setTimeout(function() {
                console.log(j, "time:" + (new Date() - start));
            }, Math.random() * 3000);
        }(i));
    }
}
forTest();
// 2 time:179
// 1 time:399
// 7 time:716
// 6 time:861
// 4 time:1375
// 9 time:1904
// 8 time:2200
// 3 time:2481
// 0 time:2520
// 5 time:2736

2. 临时解决办法:用递归

 缺点:会把请求变成串行,耗费时间

//用递归代替for循环,可以保证正常执行顺序
function recurTest(j, length) {
    setTimeout(function() {
        console.log(j, "time:" + (new Date() - start));
        if (++j < length) {
            recurTest(j, length);
        }
    }, Math.random() * 3000);
}
var start = new Date();
recurTest(0, 10);
// 0 time:74
// 1 time:354
// 2 time:2166
// 3 time:4891
// 4 time:5268
// 5 time:5466
// 6 time:6867
// 7 time:8544
// 8 time:9010
// 9 time:11170

3. ES5语法下,目前想到的最优解决办法,既保证不乱序,又让请求并行,节省时间

function forTest() {
    var arr = [];	// 缓存集
    var cursor = 0;	// 游标,用来记录输出进度
    var start = new Date();
    for (var i=0; i<10; i++) {
        (function(j) {
            setTimeout(function() {
                // 每次以对号入座形式把循环结果缓存起来
                arr[j] = (j);
                // 直到匹配到了游标,开始执行下一步
                if (j === cursor) {
                    // 在arr中,从最早的for返回的结果依次输出,直到undefined为止
                    // 每次输出后,游标也随之变化
                    for (; cursor<arr.length; cursor++) {
                        if (arr[cursor] == undefined) {
                            break;
                        }
                        console.log(arr[cursor], "time:" + (new Date() - start));
                        arr[cursor] = undefined;		// 避免重复输出,清除缓存内容
                    }
                }
            }, Math.random() * 3000);
        }(i));
    }
}
forTest();
// 0 time:1447
// 1 time:1448
// 2 time:2913
// 3 time:2914
// 4 time:2915
// 5 time:2916
// 6 time:2916
// 7 time:2916
// 8 time:2917
// 9 time:2918

4. ES6语法下,解决起来较容易了

利用let和Promise

var promiseList = [];
for (let i=0; i<10; i++) {
    promiseList.push(new Promise((resolve, reject)=> {
        setTimeout(()=> {
            resolve(i)
        }, Math.random()*3000);
    }));
}
Promise.all(promiseList).then((rspList)=> {
    rspList.map((val)=> {
        console.log(val);    // 依次输出0-9
    });
});

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值