UNPKG

w-comor-websocket

Version:

A websocket communicator in nodejs and browser. Mapping functions from nodejs to other end points, like a simple RPC.

311 lines (247 loc) 7.86 kB
import WSC from 'w-websocket-client/src/WWebsocketClient.mjs' import get from 'lodash-es/get.js' import set from 'lodash-es/set.js' import genPm from 'wsemi/src/genPm.mjs' import genID from 'wsemi/src/genID.mjs' import Evem from 'wsemi/src/evem.mjs' import j2o from 'wsemi/src/j2o.mjs' import isWindow from 'wsemi/src/isWindow.mjs' import isfun from 'wsemi/src/isfun.mjs' /** * 建立WebSocket使用者(Node.js與Browser)端物件 * * @param {Object} opt 輸入設定參數物件 * @param {String} [opt.url='ws://localhost:8080'] 輸入WebSocket伺服器ws網址,預設為'ws://localhost:8080' * @param {String} [opt.token='*'] 輸入使用者認證用token,預設為'*' * @param {Function} opt.open 輸入監聽open函數 * @param {Function} opt.close 輸入監聽close函數 * @param {Function} opt.error 輸入監聽error函數 * @param {Function} opt.reconn 輸入監聽reconn函數 * @returns {Promise} 回傳Promise,resolve為映射伺服器端可用函數之物件,各函數輸入皆為單一物件,各函數回傳皆為Promise,用resolve與reject處理回傳結果 * @example * * import WComorWebsocketClient from 'w-comor-websocket/dist/w-comor-websocket-client.umd.js' * * //opt * let opt = { * url: 'ws://localhost:8080', * token: '*', * open: function() { * console.log('client nodejs: open') * }, * close: function() { * console.log('client nodejs: close') * }, * error: function(err) { * console.log('client nodejs: error:', err) * }, * reconn: function() { * console.log('client nodejs: reconn') * }, * } * * //WComorWebsocketClient * new WComorWebsocketClient(opt) * .then(function(wo) { * console.log('client: funcs: ', wo) * * function core(ps) { * wo.group.plus(ps) * .then(function(r) { * console.log('client: plus(' + JSON.stringify(ps) + ')=' + r) * }) * .catch(function(err) { * console.log('client: plus: catch: ', err) * }) * wo.group.div(ps) * .then(function(r) { * console.log('client: div(' + JSON.stringify(ps) + ')=' + r) * }) * .catch(function(err) { * console.log('client: div: catch: ', err) * }) * wo.add(ps) * .then(function(r) { * console.log(`client: add(${JSON.stringify(ps)})=${r}`) * }) * .catch(function(err) { * console.log('client: add: catch: ', err) * }) * wo.minu(ps) * .then(function(r) { * console.log(`client: minu(${JSON.stringify(ps)})=${r}`) * }) * .catch(function(err) { * console.log('client: minu: catch: ', err) * }) * } * * let i = 100 * setInterval(function() { * i += 1 * core({ * p1: i, * p2: 10, * }) * }, 1000) * * }) * .catch(function(err) { * console.log('client: catch', err) * }) * */ function WComorWebsocketClient(opt) { let pm = genPm() let wsc = null //WebSocket let wo = {} //回傳操作物件 //ev let ev = new Evem() //env let env = isWindow() ? 'browser' : 'nodejs' // console.log('env', env) function core() { //optt let optt = { url: null, token: null, open: function() { fOpen() }, close: function() { fClose() }, message: function(data) { fMessage(data) }, error: function(err) { fError(err) }, } //default if (!opt.url) { optt.url = 'ws://localhost:8080' } if (!opt.token) { optt.token = '*' } //WebSocket, 網址傳token參數作為識別使用者 try { wsc = new WSC(optt) } catch (err) { reconn() return null } //check if (get(wsc, 'error')) { reconn() return null } //fOpen function fOpen() { if (isfun(opt.open)) { opt.open() } execFunction('getFuncs', null) } //execFunction function execFunction(func, input = null) { let pmm = genPm() //_id let _id = genID() //msg let msg = { token: opt.token, _id, func, input, } //send if (wsc.readyState === wsc.OPEN) { wsc.send(JSON.stringify(msg), function(err) { if (err) { if (isfun(opt.error)) { opt.error(err) } } }) } //等待結果回傳 ev.on(_id, function (output) { //resolve pmm.resolve(output) //removeAllListeners ev.removeAllListeners(_id) }) return pmm } //fMessage function fMessage(message) { // console.log('fMessage message', message) if (env === 'browser') { //瀏覽器端會自動轉string } else { //nodejs //message message = Buffer.from(message).toString('utf8') } //data let data = j2o(message) //get sys funcs if (get(data, 'output.sys') === 'sys' && get(data, 'output.funcs')) { //funcs let funcs = data['output']['funcs'] //clear wo wo = {} //bind funcs for (let i = 0; i < funcs.length; i++) { //func let func = funcs[i] //add func let f = function(input) { return execFunction(func, input) } set(wo, func, f) } //resolve pm.resolve(wo) } //get result if (get(data, '_id') && get(data, 'output')) { //_id let _id = get(data, '_id') //output let output = get(data, 'output') //emit ev.emit(_id, output) } } //fClose function fClose() { if (isfun(opt.close)) { opt.close() } reconn() } //fError function fError(err) { if (isfun(opt.error)) { opt.error(err) } wsc.close() } } function reconn() { setTimeout(function() { if (isfun(opt.reconn)) { opt.reconn() } core() }, 1000) } //core core() return pm } export default WComorWebsocketClient