Created
November 21, 2013 10:16
-
-
Save mpneuried/7579199 to your computer and use it in GitHub Desktop.
Backbone collection extension to solve the problem of getting a model with eventually not exists within a collection.
It also handles parallel fetches and distributes a single `.fetch()` to multiple requesters.
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
### | |
EXAMPLE USAGE | |
testColl = new Backbone.Collection.Extended() | |
# PROMISE USAGE | |
# define handlers | |
fnSuccess = -> | |
console.log( "SUCCESS", arguments ) | |
return | |
fnError = -> | |
console.log( "ERROR", arguments ) | |
return | |
# get model | |
testColl.getOrFetchId( 13 ).then( fnSuccess, fnError ) | |
# force a fetch | |
testColl.getOrFetchId( 42, true ).then( fnSuccess, fnError ) | |
# CALLBACK USAGE | |
# get model | |
testColl.getOrFetchId( 13, ( (err, model)-> | |
console.log( "CALLBACK 42 A", arguments ) | |
) ) | |
# force a fetch | |
testColl.getOrFetchId( 42, true ( (err, model)-> | |
console.log( "CALLBACK 42 B", arguments ) | |
) ) | |
### | |
class Backbone.Collection.Extended extends Backbone.Collection | |
### | |
## getOrFetchId | |
`collection.getOrFetchId( id, force, cb )` | |
Get a single model by id an fetch it from the server if it not exists within the collection. | |
It also handles parallel calles of a id and distribute a single fetch to multiple requesters | |
@param { String|Number } id The id to get | |
@param { Boolean } force Force a fetch | |
@param { Function } cb Callback function | |
@return { Promise } Instead of the callback you can use a promise syntax | |
@api public | |
### | |
getOrFetchId: ( id, force, cb )=> | |
# initialize variable to store running calls | |
@_runningGetOrFetchIds or= {} | |
# fix the arguments | |
if _.isFunction( force ) | |
cb = force | |
force = false | |
# general success handler | |
fnSuccess = ( model )=> | |
# add the model to the collection if not exists | |
@add( model, silent: true ) if not @get( id ) | |
# answer the callback if needed | |
cb( null, model ) if cb? | |
# resolve the current open promise and clear it | |
if @_runningGetOrFetchIds[ id ]? | |
@_runningGetOrFetchIds[ id ].resolve( model ) | |
@_runningGetOrFetchIds[ id ] = null | |
return | |
# general error handler | |
fnError = ( model, resp )=> | |
# answer the callback if needed | |
cb( resp or model ) if cb? | |
# reject the current open promise and clear it | |
if @_runningGetOrFetchIds[ id ]? | |
@_runningGetOrFetchIds[ id ].reject( resp ) | |
@_runningGetOrFetchIds[ id ] = null | |
return | |
# check if a fetch for this requested id is allready running | |
if @_runningGetOrFetchIds[ id ]? | |
# reuse the running promise and answer the requester with the currently running promise | |
if cb? | |
@_runningGetOrFetchIds[ id ].then( fnSuccess, fnError ) | |
return @_runningGetOrFetchIds[ id ] | |
# create a new promise | |
deferred = @_runningGetOrFetchIds[ id ] = $.Deferred() | |
# check if model allready exists | |
_model = @get( id ) | |
# on force = true or missing model fetch the model | |
if force or not _model? | |
# create a new model to fetch | |
_data = {} | |
_data[ @model.prototype.idAttribute ] = id | |
_model = new @model( _data ) | |
# run fetch and pass the results to the general handlers | |
_model.fetch( success: fnSuccess, error: fnError ) | |
else | |
# resolve the promise immediately id the model exists | |
deferred = @_runningGetOrFetchIds[ id ] = $.Deferred() | |
fnSuccess( _model ) | |
return deferred.promise() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment