通知有关服务器更改的ember-data

时间:2014-05-19 14:51:46

标签: ruby-on-rails ruby-on-rails-4 ember.js websocket ember-data

我目前正计划在rails和ember.js上使用ruby的复杂应用程序。到目前为止,我所看到的关于ember-data的是它自动缓存记录; post.comments将首先导致Ajax调用以获取给定帖子的所有注释,但如果用户下次访问相同路由,它将只从商店缓存中获取记录。

问题是:如果其他用户在此帖子中添加评论该怎么办?如何告诉ember它必须重新加载它的缓存,因为有些东西改变了?

我已经考虑过使用websockets来告诉客户重新加载哪些东西的解决方案 - 但我不认为这是最好的做法。另外,我无法想象这不是一个常见的问题,所以我想知道其他开发人员正在做些什么来解决这个问题。

4 个答案:

答案 0 :(得分:1)

如果您只是想摆脱缓存,每次用户导航到评论route时都可以强制reload。但这在很大程度上取决于你想要实现的目标,我希望comments只是一个例子。

如果您希望ui通过服务器更改自动更新,则需要与服务器进行一些通信,某些轮询机制(如websocket)或来自webworker的轮询。然后,您可以reload从服务器发送的已更改记录列表。你可能正走在正确的轨道上。

您还可以查看与Ember完美集成的orbitjs独立库。如果您还需要本地存储并且需要管理多个数据源,这将更有用。

答案 1 :(得分:1)

我尝试在(实验)聊天应用程序中实现模型更新。我在服务器端(Ruby on Rails)使用了SSEActionController::Live,在客户端使用了EventSource

简化代码:

App.MessagesRoute = Ember.Route.extend({
  activate: function() {
    if (! this.eventSource) {
      this.eventSource = new EventSource('/messages/events');

      var self = this;
      this.eventSource.addEventListener('message', function(e) {
        var data = $.parseJSON(e.data);
        if (data.id != self.controllerFor('messages').get('savedId')) {
          self.store.createRecord('message', data);
        }
      });
    }
  }
});

App.MessagesController = Ember.ArrayController.extend({
  actions: {
    create: function() {
      var data = this.getProperties('body');
      var message = this.store.createRecord('message', data);
      var self = this;
      message.save().then(function (response) {
        self.set('savedId', response.id);
      });
    }
  }
});

逻辑很简单:我从EventSource获取每条新记录。然后,如果记录是由另一个客户端创建的,则应用程序会检测到该记录,并使用ember-data createRecord将新记录添加到商店。假设这个逻辑可能有一些警告,但至少它可以很好地作为概念证明'。聊天工作正常。

此处提供完整资源:https://github.com/denispeplin/ember-chat/

关于重新加载,我有话要说:你可能不想进行完全重新加载,这是一项耗费资源的操作。不过,您的客户端需要某种方式来了解新记录。因此,通过SSE逐个获取新记录可能是最好的选择。

答案 2 :(得分:0)

无论您使用何种框架,这都是任何Web应用程序的常见问题。从我的角度来看,有两个主要选择。一:您有一个服务轮询服务器以检查是否有任何需要您重新加载某些模型的更改,让该服务返回这些模型ID并刷新它们。另一个选项是您建议的,使用websocket并推送模型更改/新模型本身的通知。

我会选择实际发送评论模型本身,然后将其推送到Ember商店和相关的帖子对象。这样可以减少使用模型的硬刷新命中服务器的需要。我目前在我的Ember应用程序中使用此方法,其中有一个对象包含基于我的应用程序中所有模型的概述数据,并且当在后端进行更改时,我的websocket服务器将新的概述数据推送到我的应用程序

更新::我的意思是这是一个评论,而不是答案,哦。好吧。

答案 3 :(得分:0)

我在移动应用开发方面遇到了同样的问题。虽然websockets似乎是第一个答案,但我担心服务器资源有限的可扩展性问题。我决定坚持使用Ajax调用来获取新修改的记录。这样,仅在用户处于活动状态时才使用服务器资源。但是,正如其他人所指出的那样,每次需要数据时都返回所有注释会使缓存变得无用而且速度很慢。我建议更新您的rails服务器以接受可选的时间戳。如果未提供时间戳,则检索每个注释。如果提供了时间戳,则仅返回updated_at列为>=提供的时间戳的注释。这样,如果自上次调用后没有添加或修改任何评论,那么您可以快速返回一个空列表并继续。如果返回结果,则可以将它们与现有列表合并,并显示更新的注释。

获取新创建或修改的评论的示例

if params.has_key?(:updated_since)
  comments = Post.find(params[:id]).comments.where("updated_at >= ?", params[:updated_since])
else
  comments = Post.find(params[:id]).comments
end