【问题标题】:Angular + web sockets, how to use promises?Angular + Web 套接字,如何使用 Promise?
【发布时间】:2015-04-16 08:12:48
【问题描述】:

我使用 Autobahn.js 进行网络套接字连接(我需要订阅套接字事件)。

我使用 $timeout 来检查套接字事件。但我认为,这是错误的,不正确的不是最佳的,我不想在控制器中使用 $timeout,也许承诺对我有帮助? 如何在没有 $timeout 的情况下在控制器中捕获套接字消息?

app.factory('socket',['$rootScope',
function($rootScope) {
    var pubsub = new ab.Session(
      'wss://site.com/',
      function(session) {
        return session;
      },
      function(code, reason) {
      }
    );
    return {
      pubsub: pubsub
    };

  }]);




app.controller('mainCtrl', ['$timeout', 'socket', function($timeout, socket) {

 $timeout(function() {
  
  $scope.data = socket.pubsub.subscribe('3434424234324', function(topic, data) { 
    
    
    // do something if data. 
    // data contains socket message.

  });
}, 300);
  
}]);

//3434424234324 - subscriber id

【问题讨论】:

  • 我发现github.com/gdi2290/angular-websocket 上的示例对我的项目很有帮助,工厂正在返回对数据流的引用,而在控制器内部,您可以将其分配给您的 $scope 变量之一。使用高速公路,您可以在这里做类似的事情。请注意,每当数据流发生变化时,angular 都会检测到它,这样您就不必手动添加 $timeout 函数来包装它。
  • 谢谢,但是我的代码实现如何?你能写吗 ? :)

标签: angularjs sockets factory angular-promise autobahn


【解决方案1】:

WebSockets 的基本思想之一是它们是异步的。您不必跟踪他们何时会做事!如果最终使用$timeout 来检查套接字是否收到了消息,那么很可能是出了点问题!那可以$timeout可以完全删除。

所有套接字接口都会公开处理回调函数,这些回调函数将负责处理套接字可以触发的不同事件。您需要做的是找到 Autobahn 的 message 事件处理程序并在那里手动触发 $scope 摘要。

Autobahn 使用发布者/订阅者模型,这意味着您需要获取 subscribe 事件处理程序:

socket.pubsub.subscribe('3434424234324', function(topic, data) { 
  // do something if data. 
  // data contains socket message.

  // let angular know something async has happened
  $scope.$apply();
});

但是,与其尝试更改所有代码以实现这种行为,我建议将 Autobahn 包装到一个 Angular 工厂中,它会为您处理这种行为。更好的是,使用像 angular-wamp 这样的库。

【讨论】:

  • 谢谢你的回答,但我是 Angular 初学者,我不能让你说:) 我需要简单的解决方案。
  • 好的,删除$timeout并将$scope.$apply();添加到您的订阅回调中。
  • socket.pubsub.subscribe('556654665', function(topic, data) { $scope.$apply(); });高速公路错误:(
  • @desp 恐怕我猜不出那个错误是什么。如果您在某事上需要帮助,则必须更新您的问题以解释问题所在。
  • 查看Autobahn docs。套接字通过connection.onopen 回调让您知道它何时已连接并准备好发送数据。如果你使用 angular-wamp,它会以更优雅的方式处理它。
【解决方案2】:

我很快想到了以下几点:

app.factory('socket',['$rootScope', function($rootScope) {
    var connection = new autobahn.Connection({
        url: 'url',
        realm: 'realm'
    });

    var collection = {
       'topic1': [],
       'topic2': []
    };

    connection.onopen = function(session) {
        session.subscribe('topic1').then(function(res){
            collection.topic1.push(res);
        });
    };

    connection.open();

    return {
       collection: collection
    }
}]);
app.controller('mainCtrl', ['socket', function(socket) {
     $scope.socket = socket;
}]);

然后在您的 mainCtrl 中,您可以访问您的主题数据,因为它们存储在集合中。如果你想在模板中显示它,你可以简单地使用 {{ socket.collection.topic1 }} 或 ng-repeat 之类的东西。

【讨论】:

  • 非常感谢!但是我不明白,什么时候应该放订阅者的id,请看i.imgur.com/WRkcdeu.png
  • 您上下文中的订阅者 ID 在我的示例中是“主题”
  • 谢谢。但我有一个错误“与'wss://site.com:34015/'的WebSocket连接失败:WebSocket握手期间出错:发送非空'Sec-WebSocket-Protocol'标头但未收到响应”。我应该使用什么版本的高速公路?
猜你喜欢
  • 2017-04-21
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 2018-12-02
  • 1970-01-01
  • 2013-09-13
相关资源
最近更新 更多