我调用getBubblesUserAccess,返回以特殊方式排序的json对象。这样的结果我想要运行一个foreach并获得其他消息,但我想在" order"中返回它们。我知道它将运行这些异步,但必须有一种方法,我可以强制它'#34;顺序"执行。 (上面的代码是我最后一次尝试添加推迟...)
示例 伪代码 - 获取我的群组
{
"id":"016cd1fc-89a3-4e4a-9e6e-a102df1b03d9",
"parent":"53750396-7d26-41f3-913d-1b93276b9e09",
"name":"XX",
"createdBy":"c9c63080-2c5b-4e8e-a093-2cfcd628a9d0",
"hasWriteAccess":true,
"hasCreateAccess":false,
"hasDeleteAccess":false,
"hasAdminAccess":false,
"settingsBubbleId":"00000000-0000-0000-0000-000000000000"
},
{
"id":"016cd1fc-89a3-4e4a-9e6e-a102df1b03d9",
"parent":"53750396-7d26-41f3-913d-1b93276b9e09",
"name":"XX",
"createdBy":"c9c63080-2c5b-4e8e-a093-2cfcd628a9d0",
"hasWriteAccess":true,
"hasCreateAccess":false,
"hasDeleteAccess":false,
"hasAdminAccess":false,
"settingsBubbleId":"00000000-0000-0000-0000-000000000000"
}
从这个结果我想迭代那些父id字符串并调用另一个响应这个的服务。
伪代码 对于上面的每个组,使用父ID调用另一个服务并获取结果。此结果将添加到新的JSON对象中。
"messages":[
{
"id":"f1d1aeda-d4e2-4563-85d5-d954c335b31c",
"text":"asd",
"sent":"2015-09-10T22:31:09.897+00:00",
"sender":"6b9e404b-ef37-4d07-9267-3e7b2579003b",
"senderName":"XXX XXXX"
},
{
"id":"a7ac0432-e945-440e-91ce-185170cbf3de",
"text":"asd",
"sent":"2015-09-10T22:28:24.383+00:00",
"sender":"c9c63080-2c5b-4e8e-a093-2cfcd628a9d0",
"senderName":"ZZZZZ ZZZZ"
},
我的问题是我的第二个foreach正在运行异步(应该如此),我希望它以与第一个json对象相同的顺序解析...
我的代码::
var loadBubblesAccess = function () {
if (vm.running && angular.isDefined(vm.running)) { return; }
vm.running = true;
vm.bubblesWithMessages = null;
return BubbleFactory.getBubblesUserAccess().then(function (bubblesAccessTo) {
return bubblesAccessTo;
});
},
loadSubBubbles = function (bubblesAccessTo) {
/**
* Result from chain method with all bubbles user has access to.
*/
var promiseArray = [];
//var promiseArrayError = [];
var i = 0;
/**
* Creates a defer object so that we will not resolve before for each loop has been gone thru.. async problems.
*/
var deferred = $q.defer();
angular.forEach(bubblesAccessTo, function (bubble) {
$log.error(JSON.stringify(bubblesAccessTo));
/**
* Get 20 because default thats default and cache and e-tags are done to that number..
*/
BubbleFactory.getBubbleMessages(bubble.id, 0, 20, false).then(function (data) {
i++;
if (data.messages.length > 0) {
promiseArray.push({ bubbleSortOrder: i, bubbleId: bubble.parent, bubbleName: bubble.name, bubbleMessagesId: bubble.id, bubbleMessages: smartTrim(data.messages[0].text, 400, ' ', ' ...'), bubbleMessagesSent: data.messages[0].sent });
}
else {
// console.log("YYYY::: " + bubble.parent);
promiseArray.push({ bubbleSortOrder:i, bubbleId: bubble.parent, bubbleName: bubble.name, bubbleMessagesId: bubble.id, bubbleMessages: 'Inget meddelande än..', bubbleMessagesSent: '' });
}
});
/**
* Check if we have gone thru all bubbles - when finished we resolve defer object.
*/
if(i===bubblesAccessTo.length)
{
deferred.resolve(promiseArray);
}
});
//$log.debug.log(promiseArray);
vm.bubblesWithMessages = promiseArray;
promiseArray.length = 0;
vm.running = false;
};
loadBubblesAccess().then(loadSubBubbles);
答案 0 :(得分:2)
AngularJS中的$q
服务被描述为“轻量级”,因为它只实现了90%的人需要的功能。这样可以减小代码大小 - 代价是无法轻松解决像你这样的请求。
如果您有选项,请尝试使用bluebird
等替代方案。 Bluebird提供了一个reduce()
函数,可以按顺序执行一系列promise,并按照请求的顺序返回结果。它使这项任务变得简单,因为您的结果数组将与您的数据数组匹配,您可以非常轻松地匹配结果。
如果你没有那个选项,那么有一个标准的(如果不是非常简单的)技术,你可以构建一个你希望承诺的元素数组,然后调用处理函数(返回一个Promise)在第一个值(从数组中弹出)。在.finally()
处理程序中,使用下一个值递归调用处理函数,直到它为空(或发生错误)。
伪代码:
var valuesToProcess = [1, 2, 3],
results = [];
function processValue(val) {
myProcessingFunction(val).then(function(result) {
results.push(result);
}).catch(function(e) {
console.log('FAIL!', e);
}).finally(function() {
if (valuesToProcess.length > 0) {
processValue(valuesToProcess.shift());
} else {
// All done - do something with results here
}
});
}
// Note: No error checking done, assumes we have work to do...
processValue(valuesToProcess.shift());
您需要根据用例进行调整,但这是一种保证串行操作和结果处理的简单技术。