2016-06-07 48 views
0

我構建了一個隨機化承諾的演示。它構建了一組可以解析1到100的promise。然後對這個數組進行洗牌並獲得結果。它的工作原理,我們可以看到它以隨機順序輸出。 (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處理程序是按隨機順序分配的,但是現在所有的promise都在等待解決!他們按原始順序逐一解決。第一個網絡請求將首先解決,然後是第二個網絡請求,依此類推。

爲了進一步說明這個情況,讓包裹forEach環在setTimeout

setTimeout(function() { 
    shuffle(promises).forEach(function(r) { 
     r.then(function(v) { 
      $('#out').append('<div>'+v+'</div>') 
     }); 
    }); 
}, 5000); 

現在,forEach循環運行後,所有承諾都解決了(假設5秒足夠了100 Ajax調用),並且數字將按照第一個示例中的隨機方式顯示。

+0

有意義。感謝您的解釋。 – Fabricator