Javascript 角度-在forEach循环中等待API调用,然后返回数组
Angular的异步化有点问题。基本上,我是在循环几张牌。特定两种类型的卡需要API调用,而非这两种类型的卡不需要任何API调用。在循环遍历所有卡之后,返回完成的卡的数组,但我只返回不需要任何API调用的卡 这是我制作的一个关于它工作原理的快速模型:Javascript 角度-在forEach循环中等待API调用,然后返回数组,javascript,angularjs,api,Javascript,Angularjs,Api,Angular的异步化有点问题。基本上,我是在循环几张牌。特定两种类型的卡需要API调用,而非这两种类型的卡不需要任何API调用。在循环遍历所有卡之后,返回完成的卡的数组,但我只返回不需要任何API调用的卡 这是我制作的一个关于它工作原理的快速模型: // If color of colorCard is blue, it needs 2 API calls // If color of colorCard is red, it needs 1 API call // If color of c
// If color of colorCard is blue, it needs 2 API calls
// If color of colorCard is red, it needs 1 API call
// If color of colorCard is yellow, it doesn't need an API call
// Pretend for this example that colorCards has one yellow card, one blue card, and two red cards
var buildCards = function() {
var finishedArray = [];
var promises = [];
colorCards.forEach(function(e, i){
if (e.color === 'blue') {
promises.push(firstBlueApiCall);
var firstBlueIdx = 0;
promises.push(secondBlueApiCall);
var secondBlueIdx = 1;
} else if (e.color === 'red') {
promises.push(redApiCall);
var redIdx = 0;
}
// If card is blue or red, complete API calls before pushing to finishedArray
if (promises.length > 0) {
$q.all(promises).then(function(response) {
if (e.color === 'blue') {
e.firstBlueData = response[firstBlueIdx];
e.secondBlueData = response[secondBlueIdx];
} else if (e.color === 'red') {
e.redData = response[redIdx];
}
finishedArray.push(e);
promises = [];
});
// If card is yellow, push to finishedArray without making any API calls
} else {
finishedArray.push(e);
promises = [];
}
})
return finishedArray;
}
在本例中,返回的finishedArray只包含一张不需要API调用的黄卡,而不是所有四张卡。我如何才能让“return finishedArray”等待红/蓝卡完成API调用?以下是我如何解决这个问题的:
var promiseFunction = function(card){
var deferred = $q.defer();
var localPromises = [];
if (card.color === 'blue') {
localPromises.push(blueApiCall1); var firstBlueIdx = promises.length - 1;
localPromises.push(blueApiCall2); var secondBlueIdx = promises.length - 1;
} else if (card.color === 'red') {
localPromises.push(redApiCall); var redIdx = promises.length - 1;
}
if (localPromises.length > 0) {
$q.all(promises).then(function(res) {
if (card.color === 'blue') {
card.firstBlueData = res[firstBlueIdx];
card.secondBlueData = res[secondBlueIdx];
} else if (card.color === 'red') {
card.redData = res[redIdx];
}
deferred.resolve(card);
});
} else {
deferred.resolve(card);
}
return deferred.promise;
}
var buildCards = function() {
var deferred = $q.defer();
var finishedArray = [];
var promises = [];
colorCards.forEach(function(card, i){
promises.push(promiseFunction(card));
});
$q.all(promises).then(function(finishedCards) {
deferred.resolve(finishedCards)
})
return deferred.promise;
}
我试着让它,所以它的承诺一路下来,它的结果很好。希望这能在将来帮助有类似问题的人。可以简化
构建卡的功能:
var buildCards = function(colorCards) {
//var deferred = $q.defer();
//var finishedArray = [];
var promises = [];
colorCards.forEach(function(card, i){
promises.push(promiseFunction(card));
});
//$q.all(promises).then(function(finishedCards) {
// deferred.resolve(finishedCards)
//})
//return deferred.promise;
return $q.all(promises);
}
由于$q.all
方法已返回承诺,因此不需要使用$q.defer
生成承诺。此外,制造承诺没有正确处理拒绝。如果任何$q.all
承诺被拒绝,则$q.defer
承诺将挂起且永远不会解决
这被称为a,应该避免
类似地,可以修改承诺功能
功能,以避免:
promise的then
方法总是返回一个新的promise,该promise解析为返回给处理函数的值。此外,如果原始承诺被拒绝,成功处理程序将被跳过,拒绝将沿着链传递到新承诺。这样可以避免错误挂起$q.defer
还请注意,如果没有承诺使用$q.all
进行处理,则可以在$q.when
时使用创建cardPromise
因为调用允诺的.then
方法会返回一个新的派生允诺,所以很容易创建允诺链。可以创建任意长度的链,并且由于一个承诺可以用另一个承诺解决(这将进一步推迟其解决),因此可以在链中的任何点暂停/推迟承诺的解决。这使得实现强大的API成为可能
--
总是连锁反应。避免使用。JavaScript是单线程的。当函数完成时,它只能返回可用的数据或将来将要实现的待定承诺。
var promiseFunction = function(card){
//var deferred = $q.defer();
var localPromises = [];
if (card.color === 'blue') {
localPromises.push(blueApiCall1); var firstBlueIdx = promises.length - 1;
localPromises.push(blueApiCall2); var secondBlueIdx = promises.length - 1;
} else if (card.color === 'red') {
localPromises.push(redApiCall); var redIdx = promises.length - 1;
}
var cardPromise;
if (localPromises.length > 0) {
//$q.all(promises).then(function(res) {
cardPromise = $q.all(localPromises).then(function(res) {
if (card.color === 'blue') {
card.firstBlueData = res[firstBlueIdx];
card.secondBlueData = res[secondBlueIdx];
} else if (card.color === 'red') {
card.redData = res[redIdx];
}
//deferred.resolve(card);
//RETURN value to chain
return card;
});
} else {
//deferred.resolve(card);
cardPromise = $q.when(card);
}
//return deferred.promise;
return cardPromise;
}