这篇文章里面,我们学习一下,怎么用 Socket.io 来流化处理一些旧金山周边的 tweet,在 nodejs 应用和 angularjs 应用之间。我们为了从 nodejs 应用拿到 tweet, 我们用的是 Twitter API 的 nodejs 客户端: Twit 。
首先,我们需要在 Twitter developers 创建一个应用。创建一个只需要读权限的应用。对我们的应用来说足够了。现在,生成你的访问 token。 你需要四个 token: Application API Key, Application API Secret, Access Token 和 Access Token Secret。
拿到旧金山周边的 tweets: 通过 nodejs 和 Twit
为了在 nodejs 中拿到 tweets, 我们需要配置 Twit。
<!-- lang: js -->
var Twit = require('twit');
var TWEETS_BUFFER_SIZE = 3;
var T = new Twit({
consumer_key: 'API Key',
consumer_secret: 'API Secret',
access_token: 'Access Token',
access_token_secret: 'Access Token Secret'
})
然后,我们可以打开一个流,指向是 /status/filter, 加上位置参数和 tweet 事件。当有推进来的时候,这个事件就会被触发。
<!-- lang: js -->
console.log("Listening for tweets from San Francisco...");
var stream = T.stream('statuses/filter', { locations: [-122.75,36.8,-121.75,37.8] });
var tweetsBuffer = [];
stream.on('connect', function(request) {
console.log('Connected to Twitter API');
});
stream.on('disconnect', function(message) {
console.log('Disconnected from Twitter API. Message: ' + message);
});
stream.on('reconnect', function (request, response, connectInterval) {
console.log('Trying to reconnect to Twitter API in ' + connectInterval + ' ms');
})
stream.on('tweet', function(tweet) {
if (tweet.geo == null) {
return ;
}
//Create message containing tweet + username + profile pic + geo
var msg = {};
msg.text = tweet.text;
msg.geo = tweet.geo.coordinates;
msg.user = {
name: tweet.user.name,
image: tweet.user.profile_image_url
};
console.log(msg);
});
在 tweet 事件里面我们通过接收到的数据,创建一个只包含推的内容,坐标,用户及用户照片的信息。现在我们看看怎么用 Socket.IO 流化这个推,在 nodejs 和 angularjs 之间交流。
Streaming tweets with Socket.IO
首先我们要配置 socket.io ,让它和 express 服务一起工作:
<!-- lang: js -->
var express = require('express');
var app = express();
var server = app.listen(3000);
var io = require('socket.io').listen(server);
现在,如果转向到 localhost:3000/socket.io/socket.io.js 我们可以拿到 socket.io 的客户端。我们只需要用我们的 socket.io 向所有链接上的客户端广播信息就可以了。因此我们要改一下 tweet 事件:
<!-- lang: js -->
stream.on('tweet', function(tweet) {
if (tweet.place == null) {
return ;
}
//Create message containing tweet + username + profile pic + location
var msg = {};
msg.text = tweet.text;
msg.location = tweet.place.full_name;
msg.user = {
name: tweet.user.name,
image: tweet.user.profile_image_url
};
//push msg into buffer
tweetsBuffer.push(msg);
//send buffer only if full
if (tweetsBuffer.length >= TWEETS_BUFFER_SIZE) {
//broadcast tweets
io.sockets.emit('tweets', tweetsBuffer);
tweetsBuffer = [];
}
});
这个方案能用,可是不是最好的一个。如果你没有服务端链接,你还是会把 tweet 到处乱发。我们得考虑带宽。为了不到处发骚,我们得记录已链接客户端。如果这个数目是 0 ,我们就不转发了。
<!-- lang: js -->
var nbOpenSockets = 0;
io.sockets.on('connection', function(socket) {
console.log('Client connected !');
if (nbOpenSockets <= 0) {
nbOpenSockets = 0;
console.log('First active client. Start streaming from Twitter');
stream.start();
}
nbOpenSockets++;
socket.on('disconnect', function() {
console.log('Client disconnected !');
nbOpenSockets--;
if (nbOpenSockets <= 0) {
nbOpenSockets = 0;
console.log("No active client. Stop streaming from Twitter");
stream.stop();
}
});
});
在 AngularJS 方通过 Socket.IO 接收信息
nodejs 应用可以取得推特,然后广播转发到已链接客户端。我们来看看如何创建一个 AngularJS 客户端。首先我们需要建立一个 service,用来链接到我们的服务器,和处理接收事件:
<!-- lang: js -->
appServices.factory('socket', function ($rootScope) {
var socket = io.connect('http://localhost:3000');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
}
};
});
然后我们可以用这个 service 来监听服务端广播出来的 tweet 事件:
<!-- lang: js -->
$scope.tweets = [];
socket.on('tweets', function (data) {
$scope.tweets = $scope.tweets.concat(data);
});
碉堡了,我们的 Angular 应用通过 Socket.IO 接收到了从 nodejs 发送过来的消息了。
来源:oschina
链接:https://my.oschina.net/u/1035386/blog/281960