[英]Array keeps outputting in random order - Push
我似乎無法弄清楚。
首先,我調用帶有無線電列表的API,然后檢查API中存在多少個無線電。
然后,我根據radio.length的長度使用“ for循環”調用另一個API,並將數據推送到數組中。
這是我使用(Angular JS)的代碼
var radioShows = [];
$http.get('http://api.example.com/radios/').success(function(results) {
var totalRadioLength = [];
for (i = 0; i <= results.length; i++) {
totalRadioLength.push(i);
console.log(totalRadioLength) // Outputs 7
$http.get('http://api.example.com/radioshows/fr/radio/' + results[i].id + '/?day=' + x + '').success(function(resultShows) {
if (resultShows.success === false) {
// console.log('No')
} else {
// console.log('Yes')
radioShows.push(resultShows);
}
})
}
})
這似乎很好用,除了每次我的數組radioShows都以隨機順序出現。 根據第一個API調用的順序獲取數組輸出的最佳方法是什么?
之所以以無法預測的順序獲得結果,是因為您按照響應到達的順序將它們放入數組中,並且不能保證請求按照發送它們的順序完成。 根據輸入數據的索引將結果放入數組中。 您可以使用一個函數來創建一個范圍,在該范圍中,每個迭代都獲得自己的變量i
:
for (i = 0; i <= results.length; i++) {
(function(i){
totalRadioLength.push(i);
console.log(totalRadioLength) // Outputs 7
$http.get('http://api.example.com/radioshows/fr/radio/' + results[i].id + '/?day=' + x + '').success(function(resultShows) {
if (resultShows.success === false) {
// console.log('No')
} else {
// console.log('Yes')
radioShows[i] = resultShows;
}
});
})(i);
}
如前所述,您的http請求同時啟動,因此解析在不同的時間進行。 最簡單的解決方案是同步發出http請求,但這是不現實的,但是有一種方法可以等待所有異步調用完成然后處理它們。
答應救援! 使用promise,您可以啟動所有http請求,但是等待它們完成后再處理它們。 但是,這會將代碼的輸出更改為一個承諾,因此,需要調用此代碼以使用返回的承諾。
var getRadioShows = function() {
// Create a promise that will resolve when all results have been compiled.
var deferredResults = $q.defer();
// Create an array that will store all of the promises
// for the async http requests
$http.get('http://api.example.com/radios/').success(function(results) {
var deferredHttpCalls = [];
for (i = 0; i <= results.length; i++) {
var deferredRequest = $q.defer();
$http.get('http://api.example.com/radioshows/fr/radio/' + results[i].id + '/?day=' + x + '').success(function(resultShows) {
if (resultShows.success === false) {
// I am guessing this is not a failure case.
// If it is then you can call deferredRequest.reject('Request was not successful');
deferredRequest.resolve();
} else {
deferredRequest.resolve(resultShows);
}
}).error(function() {
// reject this request and will also cause
// deferredResults to be rejected.
deferredRequest.reject(err);
});
// Gather all of the requests.
deferredHttpCalls.push(deferredRequest);
}
// Wait for all of the promises to be resolved.
$q.all(deferredHttpCalls).then(function(results) {
// 'results' is an array of all of the values returned from .resolve()
// The values are in the same order and the deferredHttpCalled array.
// resolve the primary promise with the array of results.
deferredResults.resolve(results);
});
}).error(function(err) {
// reject the promise for all of the results.
deferredResults.reject(err);
});
return deferredResults;
}
然后,您將使用像這樣返回承諾的調用。
getRadioShows().then(
// success function, results from .resolve
function(results) {
// process results
},
// error function, results from .reject
function(err) {
// handle error
}
)
有關$ q以及所有Promise / A +庫如何工作的更多信息,請參見以下Promise / A +標准: https : //promisesaplus.com/
看來您正在調用$http.get
每個循環。 我建議使用i
變量而不是push
存儲結果。
這樣做的原因是因為您期望每個請求花費的時間都相同,並以正確的順序推送到數組,但是在現實世界中卻並非如此。 這就是為什么該順序顯示為隨機的原因,因為它只能在結果返回時推入數組,而在等待時它已經在進行下一步。
發生這種情況是因為獲取廣播節目的請求以異步模式運行。 也許您可以使用promises同步運行請求,請檢查以下鏈接:
您還可以保存每個廣播節目的廣播ID,然后按該ID重新排列結果數組。
radioShows.push({ id: results[i].id, shows: resultShows});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.