我似乎无法解决这个问题。
首先,我使用无线电列表调用API,然后检查API中存在多少个无线电。
然后,我使用' for循环调用另一个API'根据radio.length的长度,将数据推入数组。
这是我的代码使用(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调用的顺序获得数组输出的最佳方法是什么?
答案 0 :(得分:2)
您以不可预测的顺序获得结果的原因是您按照响应到达的顺序将它们放入数组中,并且无法保证请求按您发送的顺序完成。根据输入数据的索引将结果放入数组中。您可以使用函数创建一个范围,其中每个迭代都有自己的变量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);
}
答案 1 :(得分:1)
正如已经提到的那样,你的http请求都会同时启动,并且因此而在不同时间解决。最简单的解决方案是同步生成http请求,但这是不现实的,但有一种方法可以等待所有异步调用完成然后处理它们。
承诺救援! 使用promises,你可以启动所有的http请求,但在处理它们之前等待它们完成。这会将代码的输出更改为一个承诺,所以无论如何调用它都需要更改为使用返回的promise。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/
答案 2 :(得分:0)
看起来你正在调用$http.get
每个循环。我建议使用i
变量而不是push
存储结果。
原因是因为您希望每个请求花费相同的时间并以正确的顺序推送到数组,但在现实世界中,它不是。这就是为什么订单看起来是随机的,因为它只能在结果返回时推送到数组,但它在等待时已经进入下一步。
答案 3 :(得分:0)
这种情况正在发生,因为获取电台节目的请求以异步模式运行。也许你可以使用promises同步运行请求,请查看以下链接:
how to make synchronous http request in angular js
此外,您可以保存每个广播节目的广播ID,然后按该ID重新排序结果数组。
radioShows.push({ id: results[i].id, shows: resultShows});