我构建了一个随机化promises的演示。它构建一个可以解析1到100的promises数组。然后将这个数组洗牌,并得到结果。它有效,我们可以看到它以随机顺序输出。 (fiddle)
var promises = [];
for (var i = 0; i < 100; i++) {
promises.push(new Promise(function(resolve, reject) {
resolve(i);
}));
}
// http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
var currentIndex = array.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
shuffle(promises).forEach(function(r) {
r.then(function(v) {
$('#out').append('<div>'+v+'</div>')
})
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="out">
</div>
&#13;
然而,当我在承诺中加入ajax时,结果不再是随机的。输出有时是乱序的,但大多数是按升序排列的。与前一个演示不同的部分是构建promises数组。 fiddle
var promises = [];
for (var i = 0; i < 100; i++) {
promises.push(new Promise(function(resolve, reject) {
$.ajax({
url: '/echo/json/',
data: { json: JSON.stringify({"v": i}) },
method: 'POST',
success: function(rs) {
resolve(rs.v);
}
});
}));
}
为什么?
答案 0 :(得分:1)
承诺是渴望的,这意味着它们一旦我们定义它们就会运行。
在第一个例子中,所有的promise一旦被定义就会被解析,因为里面没有异步表达式。在第二个循环(forEach
)中,每个promise都有一个then
处理程序,数据按照承诺出现在promises
数组上的顺序添加到文档中。
在第二个例子中,它实际上定义了一个异步(ajax)任务。在解决任何promise之前,解释器可能会进入秒循环(shuffle(promises).forEach
)。这意味着then
处理程序是以随机顺序分配的,但现在所有的承诺都在等待解决!他们按原始顺序一个接一个地解决。第一个网络请求将首先解析,然后是第二个网络请求,依此类推。
要进一步解释这种情况,请将forEach
循环包裹在setTimeout
中:
setTimeout(function() {
shuffle(promises).forEach(function(r) {
r.then(function(v) {
$('#out').append('<div>'+v+'</div>')
});
});
}, 5000);
现在,forEach
循环将在所有承诺解析后运行(假设5个秒足以进行100个ajax调用),并且数字将以随机方式显示,如第一个示例所示。