34936

Overriding fetch in Marionette.js model (and responding to push updates)

This is a two part question. We have a Marionette.js application wherein, on initial load, we need to "subscribe" to a Lightstreamer instance and keep that instance/connection open (not important what Lightstreamer is except that it sends updates down to the page). Subsequent model updates will generally be triggered not by user actions by by updates coming from Lightstreamer. I'm at something of a loss as to how to architect this.

Firstly, it seems like the default model fetch() action makes a web request to the model's url property and retrieves data synchronously (in most samples) based on a user action. For us, the fetch is essentially the "subscribe" action and the initial data (a collection of messages) will be returned asynchronously. I have seen suggestions to use jquery deferred, but I'm not sure where the done() function goes (in the model? in the module?).

Secondly, it seems like we'd use wreqr somehow to register for the push updates, but I'm also not sure what that would look like.

Here's some psuedo code:

MyApp.Lightstreamer = codeToGetTheLightstreamerWiredUp(); MyApp.MyCollection = Backbone.Collection.extend({ model: MyApp.Message, initialize: function(models, options) { this.id = options.id; }, fetch: function () { MyApp.Lightstreamer.Do('subscribeUpdate'), { adapterName: 'AdapterName', parameterValue: this.id, otherStuff: 'otherstuff', onUpdate: callbackFunction } }); MyApp.module("MyApp"...) { MyApp.Router = Marionette.AppRouter.extend( { appRoutes: { 'controller/view/:id', 'subscribe' } } ); var Api = { subscribe: function(id) { var messages = new MyApp.MyMessages({ id: id }); var deferred = $.Deferred(); messages.fetch({ success: deferred.resolve } } }; QaApp.addInitializer(function () { var router = new QaApp.Router( { controller: Api }); }); } <ol> <li>Question 1: where does the callbackFunction and/or how does deferred work in this case </li> <li>Question 2: how do I update this model when a push event happens that has new data (e.g., a new message to add to the collection)?</li> </ol>

Thanks!

Answer1:

Backbone's native fetch implementation can provide a template for you to follow. During a normal fetch, Backbone calls sync, passing in the following success callback:

options.success = function(resp) { var method = options.reset ? 'reset' : 'set'; collection[method](resp, options); if (success) success(collection, resp, options); collection.trigger('sync', collection, resp, options); };

Basically, when Backbone gets a response from the server, it uses this to populate the collection. Since you're getting periodic updates directly from the server, you'll want to do something a lot like this using LightStreamer's onUpdate parameter. Backbone either calls set or reset. reset will clear the collection and that sounds undesirable so you can remove the conditional and just call set. Triggering sync is optional but I'd recommend it for maximum compatibility with Marionette. I don't believe you need to worry about the deferred, unless there's some other requirement I'm missing.

Here's what I suggest:

MyApp.Lightstreamer = codeToGetTheLightstreamerWiredUp(); MyApp.MyCollection = Backbone.Collection.extend({ model: MyApp.Message, initialize: function(models, options) { this.id = options.id; // not sure if you need this but just in case LightStream changes the context on you _.bindAll(this, 'syncLightstreamResponse'); }, subscribeToLightStream: function () { MyApp.Lightstreamer.Do('subscribeUpdate'), { adapterName: 'AdapterName', parameterValue: this.id, otherStuff: 'otherstuff', onUpdate: this.syncLightstreamResponse }, syncLightstreamResponse: function(resp, /* I'm guessing here; update param list as needed */) { collection.set(resp, options); collection.trigger('sync', collection, resp, options); } }); MyApp.module("MyApp"...) { MyApp.Router = Marionette.AppRouter.extend( { appRoutes: { 'controller/view/:id', 'subscribe' } } ); var Api = { subscribe: function(id) { var messages = new MyApp.MyMessages({ id: id }); // No need for deferred here; just subscribe messages.subscribeToLightStream(); } }; QaApp.addInitializer(function () { var router = new QaApp.Router({ controller: Api }); }); }

It doesn't sound to me like you're really changing the fetch behavior so much as creating an alternative mechanism for synching the collection with the server; the point being that I don't think you need to override fetch to accomplish your goal. I've renamed your function to subscribeToLightStream, but it shouldn't matter if choose to override fetch instead.

Recommend

  • Dynamically Size Array in C
  • Querying a record with a many-to-many relationship based on whether or not it has certain correspond
  • Space behind bootstrap navbar
  • Backbonejs collection.create: how to prevent it from adding items if there is an error?
  • backbone.js router doesn't work on IE6
  • How to Remove Duplication from Spring 3 MVC Standard and Ajax Request Controllers and Views
  • Updating a LayoutView's Model
  • Property '$' of object # is not a function at _.extend._ensureElement
  • XMLHttpRequest in IE-7
  • How to communicate between ASPX and WinForms
  • ActionBar with appcompat library v7 (ava.lang.IllegalStateException: You need to use a Theme.AppComp
  • angularjs - ng-show doesn't update class when $interval triggers
  • Swift gives “self used before all stored procedures are initialized” error when building child nodes
  • docker-compose: connection refused between containers, but service accessible from host
  • Bind collection of objects to ListBox
  • Create an Event Handler whenever a new Node is added in treeview
  • Java Garbage collection, setting reference to null
  • DependencyObject.AssociatedObject is always null
  • Updating and removing unique join relationships in CakePHP
  • Curried UDF - Pyspark
  • Many to Many in Linq using Dapper
  • Why doesn't a local variable live long enough for thread::scoped?
  • Is there any way to call saveCurrentTurnWithMatchData without sending a push notification?
  • Angular Bootstrap Carousel Slide Transition not working correctly
  • jersey/tomcat Description The origin server did not find a current representation for the target res
  • Accessing Rows In A LINQ Result Without A Foreach Loop?
  • Where these are stored?
  • Android Database Error - getWriteableDatabase
  • Magento get URL before current
  • abstracting over a collection
  • How can I tell a form not to dispose a particular control when it closes?
  • Silverlight DependencyProperty.SetCurrentValue Equivalent
  • Installing iPhone App to iPhone
  • retrieve vertices with no linked edge in arangodb
  • Benchmarking RAM performance - UWP and C#
  • Acquiring multiple attributes from .xml file in c#
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • How can I remove ASP.NET Designer.cs files?
  • java string with new operator and a literal
  • How to push additional view controllers onto NavigationController but keep the TabBar?