Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit b9a56d5

Browse files
yihanghopetebacondarwin
authored andcommitted
feat($q): implement $q.race
Implement $q.race. $q.race takes in an array or hash of promises and returns a promise that resolves or rejects as soon as one of those promises resolves or rejects, with the value or reason from that promise. Closes #12929 Closes #14757
1 parent f797f83 commit b9a56d5

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

src/ng/q.js

+25
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,30 @@ function qFactory(nextTick, exceptionHandler) {
562562
return deferred.promise;
563563
}
564564

565+
/**
566+
* @ngdoc method
567+
* @name $q#race
568+
* @kind function
569+
*
570+
* @description
571+
* Returns a promise that resolves or rejects as soon as one of those promises
572+
* resolves or rejects, with the value or reason from that promise.
573+
*
574+
* @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
575+
* @returns {Promise} a promise that resolves or rejects as soon as one of the `promises`
576+
* resolves or rejects, with the value or reason from that promise.
577+
*/
578+
579+
function race(promises) {
580+
var deferred = defer();
581+
582+
forEach(promises, function(promise) {
583+
when(promise).then(deferred.resolve, deferred.reject);
584+
});
585+
586+
return deferred.promise;
587+
}
588+
565589
var $Q = function Q(resolver) {
566590
if (!isFunction(resolver)) {
567591
throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
@@ -591,6 +615,7 @@ function qFactory(nextTick, exceptionHandler) {
591615
$Q.when = when;
592616
$Q.resolve = resolve;
593617
$Q.all = all;
618+
$Q.race = race;
594619

595620
return $Q;
596621
}

test/ng/qSpec.js

+72
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,78 @@ describe('q', function() {
19721972
});
19731973
});
19741974

1975+
describe('race (array)', function() {
1976+
it('should do nothing if given an empty array', function() {
1977+
q.race([]).then(success(), error());
1978+
expect(mockNextTick.queue.length).toBe(0);
1979+
expect(logStr()).toBe('');
1980+
});
1981+
1982+
it('should resolve as soon as the first promise is settled by resolution', function() {
1983+
var deferred1 = defer(),
1984+
deferred2 = defer();
1985+
1986+
q.race([promise, deferred1.promise, deferred2.promise]).then(success(), error());
1987+
expect(logStr()).toBe('');
1988+
syncResolve(deferred1, 'hi');
1989+
expect(logStr()).toBe('success(hi)->hi');
1990+
syncResolve(deferred2, 'cau');
1991+
expect(logStr()).toBe('success(hi)->hi');
1992+
syncReject(deferred, 'hola');
1993+
expect(logStr()).toBe('success(hi)->hi');
1994+
});
1995+
1996+
it('should reject as soon as the first promise is settled by rejection', 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+
syncReject(deferred1, 'hi');
2003+
expect(logStr()).toBe('error(hi)->reject(hi)');
2004+
syncResolve(deferred2, 'cau');
2005+
expect(logStr()).toBe('error(hi)->reject(hi)');
2006+
syncReject(deferred, 'hola');
2007+
expect(logStr()).toBe('error(hi)->reject(hi)');
2008+
});
2009+
});
2010+
2011+
describe('race (hash)', function() {
2012+
it('should do nothing if given an empty array', function() {
2013+
q.race({}).then(success(), error());
2014+
expect(mockNextTick.queue.length).toBe(0);
2015+
expect(logStr()).toBe('');
2016+
});
2017+
2018+
it('should resolve as soon as the first promise is settled by resolution', function() {
2019+
var deferred1 = defer(),
2020+
deferred2 = defer();
2021+
2022+
q.race({a: promise, b: deferred1.promise, c: deferred2.promise}).then(success(), error());
2023+
expect(logStr()).toBe('');
2024+
syncResolve(deferred1, 'hi');
2025+
expect(logStr()).toBe('success(hi)->hi');
2026+
syncResolve(deferred2, 'cau');
2027+
expect(logStr()).toBe('success(hi)->hi');
2028+
syncReject(deferred, 'hola');
2029+
expect(logStr()).toBe('success(hi)->hi');
2030+
});
2031+
2032+
it('should reject as soon as the first promise is settled by rejection', function() {
2033+
var deferred1 = defer(),
2034+
deferred2 = defer();
2035+
2036+
q.race({a: promise, b: deferred1.promise, c: deferred2.promise}).then(success(), error());
2037+
expect(logStr()).toBe('');
2038+
syncReject(deferred1, 'hi');
2039+
expect(logStr()).toBe('error(hi)->reject(hi)');
2040+
syncResolve(deferred2, 'cau');
2041+
expect(logStr()).toBe('error(hi)->reject(hi)');
2042+
syncReject(deferred, 'hola');
2043+
expect(logStr()).toBe('error(hi)->reject(hi)');
2044+
});
2045+
});
2046+
19752047
describe('exception logging', function() {
19762048
var mockExceptionLogger = {
19772049
log: [],

0 commit comments

Comments
 (0)