Angular使用工厂中的Server Sent Events

时间:2014-08-05 05:24:23

标签: angularjs server-sent-events

我正在尝试在Angular / Rails应用中设置消息通知。

当用户登录时,我想打开一个SSE连接,该连接将订阅Redis流,并在用户收到新消息时向客户端发送警报。

我的SSE设置正常,但无法找到用户注销时可靠关闭SSE连接的方法。我正在尝试构建一个服务来处理SSE的开启和关闭:

angular.module('messagesApp')
.factory('StreamHandler', function(CookieHandler, MessageStream){
  var StreamHandler = {

    set: function(){
      var user
      user = CookieHandler.get();
      MessageStream.get = function(){
        var source = new EventSource('/api/v1/messages/count?id='+user.id)
        return source
      }
    },

    get: function(){
      var source = MessageStream.get()
      source.onmessage = function(event) {
        //do something
      }
    },

    kill: function(){
      var source = MessageStream.get()
      source.close()
    }
  }

  return StreamHandler
})

我无法弄清楚如何杀死StreamHandler.set()中打开的流。我在kill属性中的尝试不起作用,因为调用getter实际上会创建一个新流?

我对其他方法持开放态度:我只需要一种在用户登录/注销时设置和终止EventSource流的方法。

2 个答案:

答案 0 :(得分:2)

问题是我在我的EventSource属性中放置了创建get的函数,而不是放置实际的EventSource对象。一些变化使其有效:

.factory('StreamHandler', function(CookieHandler, MessageStream){
  var StreamHandler = {

    set: function(){
      var user
      user = CookieHandler.get();
      var source = new EventSource('/api/v1/messages/count?id='+user.id)
      MessageStream.get = source
    },

    get: function(){
      var source = MessageStream.get
      source.onmessage = function(event) {
        console.log(event)
      }
      source.onerror = function(error) {
        source.close()
      }
    },

    kill: function(){
      var source = MessageStream.get
      source.close();

    }
  }

  return StreamHandler
})

答案 1 :(得分:1)

了解Oboe.js - http://oboejs.com/examples

使用双簧管,我基本上做了(我想你不需要在这种情况下注入$ source和$ http):

.factory('MyStreamingResource', ['$resource', '$http', 
    function($resource, $http) {
      return {
        stream: function(options, startFn, nodeFn, doneFn) {
          oboe('//url/' + 'maybeSomeOptions/?maybe=' + options.passedAbove)
           .start(startFn)
           .node(options.path, nodeFn)
           .done(doneFn);
        }
      };
    }
  ]);

然后简单地注入它并从一些控制器调用:

MyStreamingResource.stream({
        passedAbove: 'foo',
        path: 'items.*'
      },
      // start callback
      function(status, headers){
        // console.dir(headers);
        // this.abort(); // could be called from here too
      },
      // node callback (where your data is going to be streamed to)
      function(data){
        if(data !== null) {
          console.dir(data);
          //this.abort();
        }
      },
      // done (if you really want to wait)
      function(parsedJson){
        // ...
      });

与您使用$ http看到的其他服务非常相似,但您需要考虑更多回调。

Oboe.js对我来说就像一个魅力和Golang go-json-rest软件包流式传输响应(即使使用无效的JSON - 这在流中非常常见,因为它们还没有完成并赢得了#t有结束标签或将有额外的逗号等)。只需确保脚本的浏览器版本包含在您的页面上,您就可以随时调用它。我花了很长时间搜索如何使用AngularJS进行此操作,但它似乎并不是一个直接的设施。如果可能的话。

当然,从这里你可以弄清楚如何使它适合你的需要...更新$ scope中的东西等。