Maintain order when resolving promise list

This updates the $qExtensions.allSettled method so that it maintains
the order of the original list of promises. The list of passed and
failed promises will be in the same order as they were in the
original list.

Closes-Bug: #1546758
Change-Id: I9de0b68a16c4f3e2a9a34fb8862de2d77b4a19bb
This commit is contained in:
Justin Pomeroy 2016-02-17 15:14:49 -06:00
parent 8157b38f97
commit e3c31b9b6a
2 changed files with 57 additions and 6 deletions

View File

@ -62,8 +62,8 @@
* promises if any promise is rejected, this will wait for all promises
* to settle.
*
* The order of the resolve or rejection reasons is non-deterministic
* and should not be relied upon for correlation to input promises.
* The order of the resolve or rejection reasons correlates directly to
* the order of the promises in the list.
*
* @param {array} promiseList
* The list of promises to resolve
@ -100,18 +100,18 @@
$q.all(promises).then(onComplete);
return deferred.promise;
function resolveSingle(singlePromise) {
function resolveSingle(singlePromise, index) {
var deferredInner = $q.defer();
singlePromise.promise.then(onResolve, onReject);
return deferredInner.promise;
function onResolve(response) {
passList.push(formatResponse(response, singlePromise.context));
passList[index] = formatResponse(response, singlePromise.context);
deferredInner.resolve();
}
function onReject(response) {
failList.push(formatResponse(response, singlePromise.context));
failList[index] = formatResponse(response, singlePromise.context);
deferredInner.resolve();
}
@ -124,7 +124,13 @@
}
function onComplete() {
deferred.resolve({pass: passList, fail: failList});
deferred.resolve({pass: condense(passList), fail: condense(failList)});
}
function condense(promiseList) {
return promiseList.filter(function removeEmpty(promise) {
return !!promise;
});
}
}

View File

@ -60,6 +60,51 @@
expect(resolvedPromises.pass[0]).toEqual({data: 'passed', context: '2'});
}
});
it('should maintain order of promises regardless of resolve/reject order', function() {
var defs = [$q.defer(), $q.defer(), $q.defer(), $q.defer(), $q.defer(), $q.defer()];
service.allSettled([{
promise: defs[0].promise,
context: '1'
},{
promise: defs[1].promise,
context: '2'
},{
promise: defs[2].promise,
context: '3'
},{
promise: defs[3].promise,
context: '4'
},{
promise: defs[4].promise,
context: '5'
},{
promise: defs[5].promise,
context: '6'
}]).then(onAllSettled);
defs[1].reject();
defs[2].resolve();
defs[0].resolve();
defs[5].reject();
defs[3].reject();
defs[4].resolve();
$scope.$apply();
function onAllSettled(resolvedPromises) {
var pass = resolvedPromises.pass;
var fail = resolvedPromises.fail;
expect(pass.length).toBe(3);
expect(fail.length).toBe(3);
expect(pass[0].context).toBe('1');
expect(pass[1].context).toBe('3');
expect(pass[2].context).toBe('5');
expect(fail[0].context).toBe('2');
expect(fail[1].context).toBe('4');
expect(fail[2].context).toBe('6');
}
});
});
describe('booleanAsPromise', function() {