total5
Version:
Total.js framework v5
219 lines (184 loc) • 4.68 kB
JavaScript
function openclientmessage(msg) {
var t = this;
if (msg.type === 'init') {
t.$opensync = msg;
for (var key in t.$clients) {
var client = t.$clients[key];
client.meta = msg;
client.type = msg.id;
client.ononline && client.ononline(msg);
}
return;
}
if (msg.callbackid) {
var cb = t.$callbacks[msg.callbackid];
if (cb) {
delete t.$callbacks[msg.callbackid];
cb.timeout && clearTimeout(cb.timeout);
cb.fn(msg.error, msg.response);
}
return;
}
for (var key in t.$clients) {
var client = t.$clients[key];
client.onmessage && client.onmessage.call(t, msg);
}
}
function openclienterror(e) {
var t = this;
for (var key in t.$callbacks) {
var cb = t.$callbacks[key];
if (cb) {
delete t.$callbacks[key];
cb.fn(e instanceof Error ? e.message : e);
}
}
for (var key in t.$clients) {
var client = t.$clients[key];
client.onerror && client.onerror.call(t, e instanceof Error ? e.message : e);
}
}
function openclientopen() {
var t = this;
for (var key in t.$clients) {
var client = t.$clients[key];
client.connected = true;
}
}
function openclientclose(code, message) {
var t = this;
for (var key in t.$clients) {
var client = t.$clients[key];
if (code > 3999)
client.onerror && client.onerror(code, message);
client.ononline && client.ononline(null);
client.connected = false;
}
}
function openclienttimeout(ws, key) {
var cb = ws.$callbacks[key];
if (cb) {
cb.fn('timeout');
cb.timeout = null;
delete ws.$callbacks[key];
}
}
exports.create = function(url, id) {
url = url.replace(/^http/, 'ws');
if (id) {
for (var key in F.openclients) {
var client = F.openclients[key];
if (client.$clients[id])
client.$clients[id].remove();
}
} else
id = GUID(10);
var opt = {};
opt.id = id;
opt.url = url;
opt.send2 = function(msg, callback, filter, timeout) {
if (typeof(filter) === 'number') {
timeout = filter;
filter = null;
}
var t = this;
if (!t.ws.closed) {
if (callback) {
var key = (t.ws.$callbackindexer++) + '';
t.ws.$callbacks[key] = { id: opt.id, fn: callback };
if (timeout)
t.ws.$callbacks[key].timeout = setTimeout(openclienttimeout, timeout, t.ws, key);
msg.callbackid = key;
}
t.ws.send(msg, filter);
} else if (callback)
callback('offline');
return !t.ws.closed;
};
opt.rpc = function(msg, callback, filter, timeout) {
if (callback && typeof(callback) !== 'function') {
timeout = filter;
filter = callback;
callback = null;
}
if (callback)
return opt.send(msg, callback, filter, timeout);
else {
var promise = new Promise((resolve, reject) => opt.send(msg, function(err, res) {
if (err) {
err.name = 'OPENCLIENT(' + opt.url + ')';
reject(err);
} else
resolve(res);
}, filter, timeout));
return promise;
}
};
opt.cmd = function(msg, filter, timeout) {
return opt.send(msg, null, filter, timeout);
};
opt.send = function(msg, callback, filter, timeout, count) {
if (!opt.ws || count > 10) {
callback && callback('offline');
return;
}
if (opt.ws.closed) {
if (opt.ws && opt.ws.$clients[opt.id])
setTimeout(opt.send, 500, msg, callback, filter, timeout, (count || 0) + 1);
else if (callback)
callback('offline');
} else
opt.send2(msg, callback, filter, timeout);
return opt;
};
opt.close = opt.remove = function() {
var t = this;
var client = t.ws.$clients[t.id];
client.destroy && client.destroy();
delete t.ws.$clients[t.id];
for (var key in t.ws.$callbacks) {
var cb = t.ws.$callbacks[key];
if (cb.id === t.id) {
cb.timeout && clearTimeout(cb.timeout);
cb.fn('offline');
delete t.ws.$callbacks[key];
}
}
if (!Object.keys(t.ws.$clients).length) {
t.ws.close();
delete F.openclients[t.url];
}
};
opt.message = function(fn) {
opt.onmessage = fn;
return opt;
};
opt.error = function(fn) {
opt.onerror = fn;
return opt;
};
opt.online = function(fn) {
opt.ononline = fn;
return opt;
};
opt.ws = F.openclients[url];
if (!opt.ws) {
opt.ws = F.websocketclient();
setImmediate(() => opt.ws.connect(url));
F.openclients[url] = opt.ws;
opt.ws.options.reconnectserver = true;
opt.ws.$clients = {};
opt.ws.$callbacks = {};
opt.ws.$callbackindexer = 0;
opt.ws.on('message', openclientmessage);
opt.ws.on('error', openclienterror);
opt.ws.on('open', openclientopen);
opt.ws.on('close', openclientclose);
} else if (!opt.ws.closed && opt.ws.$opensync) {
opt.meta = opt.ws.$opensync;
opt.type = opt.ws.$opensync.id;
opt.ononline && opt.ononline(opt.meta);
}
opt.ws.$clients[opt.id] = opt;
return opt;
};