将 SocketIO 集成到 Angular 应用程序以处理 http 请求

Posted

技术标签:

【中文标题】将 SocketIO 集成到 Angular 应用程序以处理 http 请求【英文标题】:Integrating SocketIO to an angular app for http requests 【发布时间】:2015-11-29 08:21:12 【问题描述】:

我创建了一个简单的 Angular 应用程序,它使用 Yahoo Finance 来提取一些货币数据。但是,目前它会拉取数据,但是直到我重新加载页面后,货币才发生变化,这很好。我可以在$http.get 周围创建一个简单的$timeout,但是,我更喜欢使用SocketIO

这是标准的工作$http.get:http://plnkr.co/edit/oiZ7JOASUbtLDPAQkZj2?p=preview

这里是 SocketIO 应用的开始:http://plnkr.co/edit/dUEekn6kIJwLYxikWT9H?p=preview

但是我不知道从这里去哪里,以便货币数据不断更新。

控制器:

app.controller('MainCtrl', function($scope, yahooService) 
  $scope.name = 'World';

      yahooService.getData()
        .success(function(data, status, headers, config) 
          $scope.currencies = data;
        )
        .error(function (data, status, headers, config) 
          $scope.currencies = 'There has been an error';
        );
);

服务:

app.factory('yahooService', function($http) 
    return 
        getData: function() 
            var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22USDMXN%22%2C%20%22USDCHF%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
            return $http.get(url);
        
    ;
);

套接字服务:

app.factory('socket', function ($rootScope) 
  var socket = io.connect('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22USDMXN%22%2C%20%22USDCHF%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=');
  //var socket = io.connect();
  return 
    on: function (eventName, callback) 
      socket.on(eventName, function ()   
        var args = arguments;
        $rootScope.$apply(function () 
          callback.apply(socket, args);
        );
      );
    ,
    emit: function (eventName, data, callback) 
      socket.emit(eventName, data, function () 
        var args = arguments;
        $rootScope.$apply(function () 
          if (callback) 
            callback.apply(socket, args);
          
        );
      )
    
  ;
);

任何帮助将不胜感激。

【问题讨论】:

我尝试了套接字 io 部分,但它显示该 URL 的 404。您确定端点支持 WebSocket 吗?请给我一个指向 Yahoo API 文档的链接吗? no ws for this link, and plunker send origin problem ;) 好的,如果没有 Yahoo Finance 的 web 套接字,那么某种形式的 SocketIO Finance/Currency 实时应用程序。 @FelisCatus - 雅虎 API 文档:code.google.com/p/yahoo-finance-managed/wiki/YahooFinanceAPIs @OamPsy 我检查了文档,但没有看到任何 WebSocket 内容。您的代码对我来说看起来非常好,但我们确实需要一个 WebSocket 端点来测试它。 【参考方案1】:

按照 Omkara 的建议,您可以使用 Angular 的 $interval 功能在延迟后连续执行函数。我已经分叉了你的 Plunker (http://plnkr.co/edit/edyFvnAU1LCRS4uZqJdR?p=preview) ,将你的 MainCtrl 更改为以下

app.controller('MainCtrl', function($scope, $interval, yahooService) 
  $scope.name = 'World';
    $interval(function () 
      yahooService.getData()
        .success(function(data, status, headers, config) 
          $scope.currencies = data;
        )
        .error(function (data, status, headers, config) 
          $scope.currencies = 'There has been an error';
        );
    , 1000);
);

这使控制器每 1000 毫秒执行一次您的 getData() 函数。

【讨论】:

【参考方案2】:

query.yahooapis.com 似乎不支持 WebSockets,或者至少我在他们的文档中进行了一些研究后找不到它。 WebSockets 是解决这个问题的好方法,但如果 Yahoo 没有提供它们,您将需要退回到轮询,并且按照建议,您可以使用 $interval 角度服务来完成。

Here 是你重构的代码,希望你会喜欢。

示例用法:

app.controller('MainCtrl', function($scope, yahooService) 
  yahooService.setRealTime(true);
  $scope.currencies = yahooService.getData();
);

雅虎服务实现:

app.factory('yahooService', function($http, $interval) 
  var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22USDMXN%22%2C%20%22USDCHF%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
  var realTime = false;
  var cancelIntervalCallback;
  var data = ;

  var getData = function () 
    $http.get(url).success(function(response, status, headers, config) 
      angular.merge(data, response);
    );
  ;

  return 
      getData: function() 
        if (!realTime) 
          getData(); 
        
        return data;
      , 
      setRealTime: function (isRealTime) 
        realTime = isRealTime;
        if (!isRealTime && angular.isFunction(cancelIntervalCallback)) 
          cancelIntervalCallback();
          cancelIntervalCallback = null;
         else 
          cancelIntervalCallback = $interval(getData, 1000);
        
      
  ;
);

注意:我已经将 angular.merge 功能升级到 Angular 1.4,如果这对您来说有问题,您可以使用 lodash 的合并。

【讨论】:

如果你能找到支持 WebSockets 的 API,我很乐意改变我的答案。问候。【参考方案3】:

我想建议对控制器“MainCtrl”进行一些更改,如下所示:

app.controller("MainCtrl", function($scope, $interval)

    $interval(callAtInterval, 5000);
);

function callAtInterval() 
    console.log("Invoke Get data");

【讨论】:

【参考方案4】:

您必须在 Socket 服务中添加重新连接和延迟等选项

app.factory('socket', function ($rootScope) 
      var socket = io.connect('your url',
     'reconnect': true,
      'reconnection delay': 500
);
      //var socket = io.connect();
      return 
        on: function (eventName, callback) 
          socket.on(eventName, function ()   
            var args = arguments;
            $rootScope.$apply(function () 
              callback.apply(socket, args);
            );
          );
        ,
        emit: function (eventName, data, callback) 
          socket.emit(eventName, data, function () 
            var args = arguments;
            $rootScope.$apply(function () 
              if (callback) 
                callback.apply(socket, args);
              
            );
          )
        
      ;
    );

在控制器中,如果你想显示最新的 10 种货币数据

var CURRENCIES_DISPLAYED = 10;
app.controller('MainCtrl', function($scope, yahooService) 
  $scope.name = 'World';

      yahooService.getData()
        .success(function(data, status, headers, config) 
          $scope.currencies = data;

         $scope.currencies.unshift(tx);
        if (parseInt($scope.currencies.length, 10) >= parseInt(CURRENCIES_DISPLAYED, 10)) 
          $scope.currencies = $scope.currencies.splice(0, CURRENCIES_DISPLAYED);
          
  )
        .error(function (data, status, headers, config) 
          $scope.currencies = 'There has been an error';
        );
);

【讨论】:

以上是关于将 SocketIO 集成到 Angular 应用程序以处理 http 请求的主要内容,如果未能解决你的问题,请参考以下文章

Flask 和 Flask-SocketIO 集成和导入错误

Bazel + Angular + SocketIO V3 原因:Uncaught TypeError: XMLHttpRequest is not a constructor

将 Select2 集成到 Angular2 应用程序中

使用 ng-recaptcha 将 Google reCaptcha v3 集成到 Angular 应用程序中

将 Sails Js 与 Angular 2 集成

将 Angular 和 .net core web api 安全地集成到现有的 MVC 5 应用程序中