2

这是一个两部分的问题。我们有一个 Marionette.js 应用程序,其中,在初始加载时,我们需要“订阅”一个 Lightstreamer 实例并保持该实例/连接打开(Lightstreamer 是什么并不重要,只是它将更新发送到页面)。后续模型更新通常不会由来自 Lightstreamer 的更新由用户操作触发。我对如何构建它感到不知所措。

首先,默认模型 fetch() 操作似乎向模型的 url 属性发出 Web 请求,并根据用户操作同步检索数据(在大多数示例中)。对我们来说,获取本质上是“订阅”操作,初始数据(消息集合)将异步返回。我已经看到了使用 jquery deferred 的建议,但我不确定 done() 函数在哪里(在模型中?在模块中?)。

其次,我们似乎会以某种方式使用 wreqr 来注册推送更新,但我也不确定那会是什么样子。

这是一些伪代码:

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. 问题 1:callbackFunction 和/或 deferred 在这种情况下如何工作
  2. 问题 2:当发生具有新数据的推送事件(例如,要添加到集合中的新消息)时,如何更新此模型?

谢谢!

4

1 回答 1

1

Backbone 的原生fetch实现可以提供一个模板供您遵循。在正常获取期间,Backbone 调用sync,传入以下成功回调:

  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);
  };

基本上,当 Backbone 从服务器获得响应时,它会使用它来填充集合。由于您直接从服务器获取定期更新,因此您需要使用 LightStreamer 的onUpdate参数执行类似这样的操作。骨干网调用setreset. reset将清除集合,这听起来不受欢迎,因此您可以删除条件并调用set. 触发sync是可选的,但我推荐它以最大限度地与 Marionette 兼容。我不相信您需要担心延期,除非我缺少其他一些要求。

这是我的建议:

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
      });
  });
}

在我看来,您并没有真正改变fetch行为,而是创建了一种将集合与服务器同步的替代机制;关键是我认为你不需要重写fetch来实现你的目标。我已将您的函数重命名为subscribeToLightStream,但如果选择覆盖则无关紧要fetch

于 2013-09-05T01:25:49.230 回答