随机化使用ajax的promise

时间:2016-06-07 18:03:04

标签: javascript jquery ajax promise

我构建了一个随机化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;
&#13;
&#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);
      }
    });
  }));
}

为什么?

1 个答案:

答案 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调用),并且数字将以随机方式显示,如第一个示例所示。