将 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