Skip to content

Instantly share code, notes, and snippets.

@Kosmin
Last active September 15, 2015 19:33
Show Gist options
  • Save Kosmin/88cdf0727956b8bb7b59 to your computer and use it in GitHub Desktop.
Save Kosmin/88cdf0727956b8bb7b59 to your computer and use it in GitHub Desktop.
Angular Promise Queuer
module = angular.module 'helpers.promise_queuer'
# Lets us ensure that some promises don't execute if others are in progress
# within a given context
#
# Notes:
# This also helps us decouple the queuing logic from our promises.
###
Architecture Notes:
=> Want to maintain the order in which the promises were queued
=> Need to ensure that promises dont even start unless previous ones finish
1) All operations are added to a queue
2) Whenever any operation finishes, a dequeue process is started
3) If a dequeue process is already started, don't start a new one
###
module.service "PromiseQueuer", [
"$q"
($q) ->
operationQueue = {}
dequeueInProgress = false
dequeue = (scopeName) ->
callback = operationQueue[scopeName].shift()
if callback
callback().finally (data) =>
# If no more operations in the queue, stop dequeuing
if operationQueue[scopeName].length == 0
dequeueInProgress = false
data
else
dequeue(scopeName)
# Begin dequeing all operations in queue
startDequeue = (scopeName) ->
return if dequeueInProgress
dequeueInProgress = true
dequeue(scopeName)
perform = (scopeName, callback, deferred) ->
result = callback()
# If callback returns a promise
if result.then
result.then(
(data) =>
deferred.resolve(data)
, (response) =>
deferred.reject(response)
)
# Otherwise, just return a resolved promise
else
deferred.resolve(result)
deferred.promise
api = {}
api.enqueue = (scopeName, callback) ->
deferred = $q.defer()
operationQueue[scopeName] ||= []
operationQueue[scopeName].push => perform(scopeName, callback, deferred)
startDequeue(scopeName)
deferred.promise
api
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment