可直接看第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
});
});