2016-06-07 2 views
0

Я построил демоверсию, которая рандомизирует обещания. Он создает массив обещаний, которые разрешат от 1 до 100. Затем перетасуйте этот массив и получите результаты. Он работает, и мы можем видеть его выходы в случайном порядке. (fiddle)Рандомизировать обещания, которые используют ajax

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) { 
 
    \t $('#out').append('<div>'+v+'</div>') 
 
    }) 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="out"> 
 
</div>

Однако, когда я включаю Аякс в обещании, то результат уже не случайный. Результат иногда не в порядке, но в основном в порядке возрастания. Часть, которая отличается от предыдущей демонстрации, заключается в создании массива обещаний. 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

Обещания нетерпеливы, это означает, что они запускаются, как только мы их определяем.

В первом примере все обещания фактически разрешены, как только они определены, потому что внутри не существует асинхронного выражения. Во втором цикле (forEach) каждое обещание получает обработчик then, и данные добавляются в документ в том же порядке, что и обещания в массиве promises.

Во втором примере это немного отличается, вы фактически определяете асинхронную задачу (ajax). Вероятно, переводчик попадает в цикл секунд (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 АЯКСА звонков), и цифры будут отображаться случайным образом, как в первом примере.

+0

иметь смысл. Спасибо за объяснение. – Fabricator

Смежные вопросы