In summary : Absolutely, simply return regular values from synchronous methods and include them as input parameters in $q.all
. It will handle them properly.
Detailed explanation
Upon examining the angular code for $q.all
, we can see at this line how input parameters are managed:
function all(promises) {
....
forEach(promises, function(promise, key) {
....
ref(promise).then(function(value) {
Each parameter is sent to the ref
function detailed at this line. The ref
function evaluates the argument; if it's a promise, it returns it
if (value && isFunction(value.then)) return value;
If the argument isn't a promise, it wraps the value with a new promise that is returned. This promise resolves as quickly as possible, but not within the current event loop iteration.
return {
then: function(callback) {
var result = defer();
nextTick(function() {
result.resolve(callback(value));
});
return result.promise;
}
};
Hence, it is safe to return non-promise values from synchronous methods.
function asyncFirst() {
var def = $q.defer();
$timeout(function(){
$scope.first = true;
def.resolve();
}, 1000);
return def.promise;
}
function syncSecond() {
$scope.second = true;
return {
data1: 'abc',
data2: 123
};
}
$q.all([
asyncFirst(),
syncSecond()
])
.then(function(){
$scope.all = true;
});
View this concept in action through this jsbin example
EDIT:
According to user @Bergi's suggestion, any normal value could be transformed into a promise using $q.when
source However, $q.when
utilizes the ref
function to convert the value to a promise and resolve it in the subsequent event loop iteration. Technically speaking, the method itself is synchronous since it completes without delays. Nevertheless, the end outcome involves the immediate wrapping of the result into a promise, postponing its usage until the next event loop iteration. Therefore, although the synchronous method is treated as asynchronous within $q.all
, it ultimately gets resolved in the upcoming iteration. Keep this point in mind.