I have an array queue
that I push objects to it when they are modified. If the user presses save
, then I will loop through the queue
and apply the appropriate API call for them.
If the API call goes through successfully, I want to remove the item from the queue
, otherwise keep it inside and notify the user that some items were not successfully saved. I currently have this (in AngularJS)
var unsuccessfulItems = [];
var promise = queue.map(function(item) {
var defer = $q.defer();
myCallFunction( item
, function( response ) {} // Success
, function( response ) { // Error
unsuccessfulItems.push(item);
}
)
defer.resolve();
return defer.promise;
})
// Once all items have been processed
$q.all( promise ).then( function() {
queue = unsuccessfulItems;
});
Is there a better way of doing this?
You're already using promises, you might want to do it end-to-end. Also, you're resolving the promise too early.
Assuming the suboptimal case where you don't want to promisify
myCallFunction
itself, you should still promisify it.Note, we are resolving the defer after the asynchronous function is done, not before it.
Now, we need to implement a "Settle" function, that resolves when all promises are done no matter what. This is like
$q.all
but will wait for all promises to resolve and not fulfill.This sort of settle function exists in most promise implementations but not in
$q
. We could have also done this with rejections and$q.all
, but that would mean exceptions for flow control which is a bad practice.Now, we can
settle
:Here's a concise solution that works around the limitations of the very limited $q, without the need to augment its methods with bulky functions/polyfills.
In particular,
.all()
method but notallSettled()
.The tricks I employ here are :
$q.all()
to behave like the missing$q.allSettled()
.saveQueue()
will return :saveQueue()
is still in progress, orPurists will undoubtedly deem this solution an "antipattern" (yuk!) due to the need to resolve promises on both success and error, however the nature of the problem and the limitations of $q encourage us in this direction.
In addition to all this, you will probably need a mechanism to ensure that items placed in the queue are unique. Duplicates would be at best wasteful, and at worst may cause errors.