Last active
August 29, 2015 14:18
-
-
Save mzipay/78ce922b717d60899953 to your computer and use it in GitHub Desktop.
INDEPENDENT parallel promises with AngularJS $q.all
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* @license CC0 1.0 (http://creativecommons.org/publicdomain/zero/1.0/) | |
* | |
* Angular's $q.all works great for cases where a rejection of any one promise | |
* SHOULD cause all parallel promises to be rejected... but it's not so great | |
* when you've got a number of promises that need to run in parallel and you | |
* don't want a single rejection to reject the entire $q.all promise. | |
* (One example: think aggregating data from multiple APIs.) | |
* | |
* This gist shows one way to "partially resolve" parallel processes when at | |
* least one $q.all promise is rejected. To keep the code concise and focused, | |
* just imagine that itGetsResolved.query() and itGetsRejected.query() return | |
* $http.get promises that do what they suggest (get resolved and rejected, | |
* respectively). | |
*/ | |
var example = angular.module('independent-parallel-promises', [ | |
'it-gets-resolved-service', | |
'it-gets-rejected-service' | |
]); | |
example.service('aggregator', ['$q', '$log', function($q, $log) { | |
/** @private */ | |
function keepResponse(response) { | |
return response; | |
} | |
/** @private */ | |
function logAndKeepError(e) { | |
$log.error('rejected query', e.config.url); | |
return e; | |
} | |
this.aggregate = function() { | |
return $q(function(resolve, reject) { | |
$q.all([ | |
itGetsResolved.query().then(keepResponse).catch(logAndKeepError), | |
itGetsRejected.query().then(keepResponse).catch(logAndKeepError) | |
]) | |
.then(function(responses) { | |
// it's up to YOU whether to resolve or reject the aggregate promise! | |
resolve({ | |
'it-gets-resolved-response': responses[0], // array of whatever | |
'it-gets-rejected-response': responses[1] // an Error object | |
}); | |
}); | |
// NOTE: q.all.catch won't be invoked in this scenario | |
}); | |
}; | |
}]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @license CC0 1.0 (http://creativecommons.org/publicdomain/zero/1.0/) | |
* | |
* An alternative implementation of the 'aggregator' service that simply | |
* uses an empty array instead of an Error object when a promise is rejected, | |
* and resolves with a concatenated array of all responses. | |
*/ | |
example.service('aggregator', ['$q', '$log', function($q, $log) { | |
/** @private */ | |
function keepResponse(response) { | |
return response; | |
} | |
/** @private */ | |
function logAndIgnoreError(e) { | |
$log.error('ignoring rejected query', e.config.url); | |
return []; | |
} | |
this.aggregate = function() { | |
return $q(function(resolve, reject) { | |
$q.all([ | |
itGetsResolved.query().then(keepResponse).catch(logAndIgnoreError), | |
itGetsRejected.query().then(keepResponse).catch(logAndIgnoreError) | |
]) | |
.then(function(responses) { | |
resolve( | |
responses[0] // array of whatever | |
.concat(responses[1]) // empty array | |
); | |
}); | |
}); | |
}; | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment