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

前提是你 提交于 2019-12-11 01:45:25

问题


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
      });
  });
}
  1. Question 1: where does the callbackFunction and/or how does deferred work in this case
  2. 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)?

Thanks!


回答1:


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.



来源:https://stackoverflow.com/questions/18625203/overriding-fetch-in-marionette-js-model-and-responding-to-push-updates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!