Skip to content

Instantly share code, notes, and snippets.

@ryanabel03
Created March 27, 2016 23:46
Show Gist options
  • Save ryanabel03/ead76192df9b670a14f5 to your computer and use it in GitHub Desktop.
Save ryanabel03/ead76192df9b670a14f5 to your computer and use it in GitHub Desktop.
Ember.js Network Request Retries
ApplicationAdpater = DS.ActiveModelAdapter.extend
synchronizer: Em.inject.service()
ajax: (url, type, options) ->
hash = @ajaxOptions(url, type, options)
# set up hash.success & hash.error callbacks normally
@get('synchronizer').handleRequest(hash)
afterModel: (resolvedModel) ->
# Load from local storage
@get('synchronizer.syncQueue').loadStateFromPersistentStorage(user.get('id')).then (entries) ->
if entries.length > 0
# Re-populate queue
@get('synchronizer.syncQueue').replaceWithEntries(entries)
# start syncing
@get('synchronizer').startSync()
StorageService = Em.Object.extend
init: ->
@set 'maxOrder', 0
@set 'localForage', localforage
@populateMaxOrder()
# The request order is determined by what already exists in local storage
populateMaxOrder: ->
new Em.RSVP.Promise (resolve, reject) =>
@get('localForage').iterate (value, key, index) =>
if @get('maxOrder') < value.order
@set 'maxOrder', value.order
return
modelJson = @get('syncModelRepository').jsonForModel entry.get('model')
serialized = {
id: @idForEntry(entry) # Generate UUID to identify entry
order: @get('maxOrder') + 1
queueEntry: @get('syncQueueEntryRepository').jsonForEntry(entry) # Serialize entry for storage
model: modelJson
}
new Em.RSVP.Promise(resolve, reject) =>
@get('localforage').setItem(@idForEntry(entry), serialized).then (value) =>
resolve(value)
, (err) =>
reject(err)
SyncQueue = Em.Object.extend
init: ->
@set 'queue', []
pushEntry: (entry) ->
@get('queue').pushObject(entry)
@get('storageService').pushEntry(entry)
Synchronizer = Em.Object.extend
handleRequest: (opts) ->
# Create an object that describes the request
@get('syncQueueEntryRepository').entryForJqueryOpts(opts).then (entry) =>
# Push that object into local storage
@get('syncQueue').pushEntry(entry).finally =>
# Tell the application that the request was successful
opts.success({}, "success", entry)
processRequests: ->
entry = @get('syncQueue.firstObject')
if entry?
# deserialize entry into request
opts = @get('syncQueueEntryRepository').jqueryOptsForEntry(entry)
# Make the request
Ember.$.ajax(opts).then (result) =>
# Success case
Em.run =>
# Request was successful, so remove that entry
@get('syncQueue').removeEntry(entry).then (val) =>
# Push resulting objects into the Store
@handleResponse(result, entry)
# Process the next request
Em.run.once @, 'processRequest'
, if ((not jqXHR.readyState?) or jqXHR.readyState == 0)
# Connectivity problem -- keep retrying
Em.run =>
# Update a retry timer
@_backoffRetrySyncTime()
# Re-run the request after the backoff has ended
Ember.run.later @, 'processRequest', @get('retrySyncInSeconds') * 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment