landers.angular
Version:
landers.angular
180 lines (157 loc) • 7.38 kB
JavaScript
;angular.module('Landers.angular')
// 建立web socket连接,对象存在rootScope下,方便全局调用
// 监听web socket发来的消息,由rootScope进行广播
.provider('GWebSocket', function(){
var provider = this;
this.connections = null;
this.showLog = false;
this.onOpen = null;
// 初始化超时时间
var initialTimeout = 1500;
// 设置是否断开自动重连
var reconnectIfNotNormalClose = true;
// 所有的连接
var connections = {};
// var is_api_result = function(rspn) {
// if ( !angular.isObject(rspn)) return false;
// return 'success' in rspn &&
// 'message' in rspn &&
// 'status_code' in rspn &&
// 'response_code' in rspn &&
// ('data' in rspn || 'errors' in rspn);
// };
this.$get = ['$rootScope','$websocket', function($rootScope, $websocket) {
if (!provider.connections) {
return;
};
var build_event = function(connection, cmd){
return [connection, cmd].join(':');
};
var initWs = function(connection, ws_url){
var ws = $websocket(ws_url);
// 设置断开自动重连
ws.reconnectIfNotNormalClose = reconnectIfNotNormalClose;
// 设置初始化连接超时时间
ws.initialTimeout = initialTimeout;
// 设置创建连接时的回调函数,发送认证信息到服务器
ws.onOpen(function () {
provider.onOpen && provider.onOpen();
});
// 设置回调函数,收到消息后向全局广播
ws.onMessage(function (msg) {
if (msg && msg.data) {
var result = angular.fromJson(msg.data);
var handler = result.cmd || result.handler;
var data = result.data;
var event = build_event(connection, handler);
show_log('receive message:', event, data);
// 广播至各个scope
$rootScope.$broadcast(event, data);
}
});
ws.onClose(function() {
show_log('websocket ' + connection + ' is closed', '', '');
});
return ws;
};
var watcher = {
key: '$WebsocketListers',
init: function(scope, connection){
if (!scope.hasOwnProperty(this.key)) {
scope[this.key] = {};
}
if (!scope[this.key][connection]) {
scope[this.key][connection] = {};
}
},
get: function(scope, connection, cmd) {
this.init(scope, connection);
return scope[this.key][connection][cmd];
},
add: function(scope, connection, cmd, on_result) {
this.init(scope, connection);
scope[this.key][connection][cmd] = on_result;
},
remove: function(scope, connection, cmd) {
this.init(scope, connection);
delete scope[this.key][connection][cmd];
}
};
var send = function(connection, scope, cmd_handler, data, lisener){
//cmd:命令格式统一为类名_方法名,例如user_login
//handler:命令格式统一为类名_方法名,例如user_login
//data:json对象包
var pack = {
cmd: cmd_handler,
data: data,
handler: cmd_handler
};
if ( lisener && !watcher.get(scope, connection, cmd_handler)) {
var event = build_event(connection, cmd_handler);
var ret = scope.$on(event, lisener);
watcher.add(scope, connection, cmd_handler, ret);
}
return connections[connection].ws.send(angular.toJson(pack));
};
var show_log = function(msg, cmd, data) {
if (provider.showLog) {
console.log(msg, cmd, data);
}
};
for (var connection in provider.connections) {
connections[connection] = connections[connection] || (function(url){
var ws_protocol = window.location.protocol.substring(0,5) == 'https' ? 'wss' : 'ws';
var ws_url = ws_protocol + '://' + url;
return {
ws: initWs(connection, ws_url),
authed: false,
onOpen: null
};
})(provider.connections[connection]);
}
return {
// 发送请求到服务端
send: function(connection, scope, cmd, data, lisener){
if (!scope) return;
if ( connections[connection].authed || true) {
send(connection, scope, cmd, data, lisener)
.then(function () {
show_log('success to send message:', cmd, data);
}, function () {
// 发送失败的消息会被push到ws对象的sendQueue数组中
show_log('failed to send message:', cmd, data);
});
} else {
var self = arguments.callee;
setTimeout(function(){
self(connection, scope, cmd, data, lisener);
}, 500);
}
},
cancel: function(connection, scope, cmd){
var destroyWatch = watcher.get(scope, connection, cmd);
if ( destroyWatch ) {
destroyWatch();
watcher.remove(scope, connection, cmd);
}
},
auth : function(connection, handler, ws_token, callback) {
if ('authed' in connections[connection]) {
connections[connection].onOpen = function(){
send(connection, $rootScope, handler, {token: ws_token}, function(event, response){
connections[connection].authed = response.success;
callback && callback();
});
}
}
['user_need_login', 'need_auth'].map(function(item){
var event = build_event(connection, item);
$rootScope.$on(event, function(){
connections[connection].onOpen();
});
});
connections[connection].onOpen();
}
};
}];
});