Skip to content

Commit fac6030

Browse files
committed
feat($q): implement $q.race
Implement $q.race. $q.race takes in an array or hash of promises and returns a promsie that is resolved as soon as the first promise is resolved. Closes angular#12929
1 parent 3ddf2f6 commit fac6030

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/ng/q.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,34 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
636636
return deferred.promise;
637637
}
638638

639+
/**
640+
* @ngdoc method
641+
* @name $q#race
642+
* @kind function
643+
*
644+
* @description
645+
* Returns a promise that is resolved similarly as the first promise to resolve.
646+
*
647+
* @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
648+
* @returns {Promise} Returns a promise that will be resolved as soon as the first promise in
649+
* `promises` is resolved. The resolved value will be the same as the value of the first
650+
* resolved promise.
651+
*/
652+
653+
function race(promises) {
654+
var deferred = new Deferred();
655+
656+
forEach(promises, function(promise) {
657+
when(promise).then(function(value) {
658+
deferred.resolve(value);
659+
}, function(reason) {
660+
deferred.reject(reason);
661+
});
662+
});
663+
664+
return deferred.promise;
665+
}
666+
639667
var $Q = function Q(resolver) {
640668
if (!isFunction(resolver)) {
641669
throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
@@ -665,6 +693,7 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) {
665693
$Q.when = when;
666694
$Q.resolve = resolve;
667695
$Q.all = all;
696+
$Q.race = race;
668697

669698
return $Q;
670699
}

test/ng/qSpec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,42 @@ describe('q', function() {
19861986
});
19871987
});
19881988

1989+
describe('race', function() {
1990+
it('should do nothing if given an empty array', function() {
1991+
q.race([]).then(success(), error());
1992+
expect(mockNextTick.queue.length).toBe(0);
1993+
expect(logStr()).toBe('');
1994+
});
1995+
1996+
it('should resolve as soon as the first promise is settled by resolution', function() {
1997+
var deferred1 = defer(),
1998+
deferred2 = defer();
1999+
2000+
q.race([promise, deferred1.promise, deferred2.promise]).then(success(), error());
2001+
expect(logStr()).toBe('');
2002+
syncResolve(deferred1, 'hi');
2003+
expect(logStr()).toBe('success(hi)->hi');
2004+
syncResolve(deferred2, 'cau');
2005+
expect(logStr()).toBe('success(hi)->hi');
2006+
syncReject(deferred, 'hola');
2007+
expect(logStr()).toBe('success(hi)->hi');
2008+
});
2009+
2010+
it('should reject as soon as the first promise is settled by rejection', function() {
2011+
var deferred1 = defer(),
2012+
deferred2 = defer();
2013+
2014+
q.race([promise, deferred1.promise, deferred2.promise]).then(success(), error());
2015+
expect(logStr()).toBe('');
2016+
syncReject(deferred1, 'hi');
2017+
expect(logStr()).toBe('error(hi)->reject(hi)');
2018+
syncResolve(deferred2, 'cau');
2019+
expect(logStr()).toBe('error(hi)->reject(hi)');
2020+
syncReject(deferred, 'hola');
2021+
expect(logStr()).toBe('error(hi)->reject(hi)');
2022+
});
2023+
});
2024+
19892025
describe('exception logging', function() {
19902026
var mockExceptionLogger = {
19912027
log: [],

0 commit comments

Comments
 (0)