add .gitignore and .prettierrc.js
This commit is contained in:
parent
6ea84fc811
commit
90c18ea708
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
/test/unit/coverage/
|
||||||
|
/test/e2e/reports/
|
||||||
|
selenium-debug.log
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
/package-lock.json
|
16
.prettierrc.js
Normal file
16
.prettierrc.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
对 VSCode Prettier 有效;建议一直要有本配置文件,否则不同版本的 Prettier 的默认配置会不同,例如 TrailingComma
|
||||||
|
对 VSCode Prettier Standard 无效,似乎是集成了不能修改的配置。
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
printWidth: 160, // default 80
|
||||||
|
tabWidth: 2, // default 2
|
||||||
|
useTabs: false,
|
||||||
|
semi: false, // default true
|
||||||
|
singleQuote: true, // default false
|
||||||
|
trailingComma: 'es5', // none (default in v 1.*), es5 (default in v2.0.0), all
|
||||||
|
bracketSpacing: true, // default true
|
||||||
|
jsxBracketSameLine: false, // default false
|
||||||
|
arrowParens: 'always', // avoid (default in v1.9.0), always (default since v2.0.0)
|
||||||
|
quoteProps: 'as-needed', // as-needed (default), consistent, preserve
|
||||||
|
}
|
161
index.js
161
index.js
@ -1,132 +1,141 @@
|
|||||||
const ws = require('ws')
|
const ws = require('ws')
|
||||||
const {randomBytes} = require('crypto')
|
const { randomBytes } = require('crypto')
|
||||||
const sleep = (ms)=>new Promise((resolve, reject)=>setTimeout(resolve, ms))
|
const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))
|
||||||
|
|
||||||
// 建议把 onopen, onerror, onclose, onmessage 保留给系统使用,例如reconnecting。用户使用 on(event, listener)
|
// 建议把 onopen, onerror, onclose, onmessage 保留给系统使用,例如reconnecting。用户使用 on(event, listener)
|
||||||
|
|
||||||
const DAD = module.exports = class TicSocket extends ws {
|
const DAD = (module.exports = class RpcSocket extends (
|
||||||
constructor(address, protocols, options){
|
ws
|
||||||
|
) {
|
||||||
|
constructor(address, protocols, options) {
|
||||||
let ws = super(address, protocols, options)
|
let ws = super(address, protocols, options)
|
||||||
DAD.upgrade(ws)
|
DAD.upgrade(ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
static upgrade(ws){
|
static upgrade(ws) {
|
||||||
ws.__proto__ = DAD.prototype
|
ws.__proto__ = DAD.prototype
|
||||||
ws.sid = randomBytes(16).toString('hex')
|
ws.sid = randomBytes(16).toString('hex')
|
||||||
ws.onMessage()
|
ws.onmessage = async ({ data }) => {
|
||||||
|
// console.log('onmessage 被调用')
|
||||||
|
try {
|
||||||
|
let obj = JSON.parse(data)
|
||||||
|
// console.log('message data parsed to obj=',obj)
|
||||||
|
switch (obj.type) {
|
||||||
|
case 'NOTIFY': // 接收到同步的远程调用
|
||||||
|
// console.log(`NOTIFY message: rpc=${obj.rpc}, param=${JSON.stringify(obj.param)}`)
|
||||||
|
if (ws.hasOwnProperty(obj.rpc))
|
||||||
|
// 作为rpc调用
|
||||||
|
ws[obj.rpc](obj.param)
|
||||||
|
else if (ws.eventNames().indexOf(obj.rpc) >= 0)
|
||||||
|
// 作为event调用
|
||||||
|
ws.emit(obj.rpc, obj.param)
|
||||||
|
else console.log('onmessage unknown notification')
|
||||||
|
case 'REQUEST': // 接收到异步的远程调用
|
||||||
|
// console.log(`被动方 收到 REQUEST: rpc=${obj.rpc}, param=${JSON.stringify(obj.param)}`)
|
||||||
|
let result
|
||||||
|
if (ws.hasOwnProperty(obj.rpc)) {
|
||||||
|
result = await ws[obj.rpc](obj.param)
|
||||||
|
} else {
|
||||||
|
result = { _state: 'error', error: 'unknown rpc' }
|
||||||
|
}
|
||||||
|
if (obj.randomEvent) {
|
||||||
|
ws.send(
|
||||||
|
JSON.stringify({
|
||||||
|
type: 'REPLY',
|
||||||
|
randomEvent: obj.randomEvent,
|
||||||
|
result,
|
||||||
|
})
|
||||||
|
) // 返回结果给远程
|
||||||
|
}
|
||||||
|
case 'REPLY': // 接收到远程返回的结果
|
||||||
|
// console.log('主动方 收到 REPLY: result=', obj.result)
|
||||||
|
ws.emit(obj.randomEvent, obj.result)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
} catch (exception) {
|
||||||
|
console.error('Invalid socket message received!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ws
|
return ws
|
||||||
}
|
}
|
||||||
|
|
||||||
static connectAsync(url) {
|
static connectAsync(url) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
let socket = new DAD(url)
|
let socket = new DAD(url)
|
||||||
socket.onopen = ()=>resolve(socket)
|
socket.onopen = () => resolve(socket)
|
||||||
socket.onerror = (err)=>reject(err)
|
socket.onerror = (err) => reject(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnectAsync(url){
|
reconnectAsync(url) {
|
||||||
if ( this.readyState < 2 ) {
|
if (this.readyState < 2) {
|
||||||
return Promise.resolve(this)
|
return Promise.resolve(this)
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject)=>{
|
return new Promise((resolve, reject) => {
|
||||||
let socket = new DAD(url || this.url)
|
let socket = new DAD(url || this.url)
|
||||||
socket.once('open', ()=>resolve(socket))
|
socket.once('open', () => resolve(socket))
|
||||||
socket.once('error', (err)=>reject(err))
|
socket.once('error', (err) => reject(err))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
notify({rpc, param, options, cb}={}){ // 发起同步的远程调用
|
notify({ rpc, param, options, cb } = {}) {
|
||||||
this.send(JSON.stringify({type:'NOTIFY', rpc, param, options, cb}))
|
// 发起同步的远程调用
|
||||||
|
this.send(JSON.stringify({ type: 'NOTIFY', rpc, param, options, cb }))
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAsync( { rpc, param, ack, timeout = 5000 } = {} ) { // 发起异步的远程调用(rpc)
|
requestAsync({ rpc, param, ack, timeout = 5000 } = {}) {
|
||||||
|
// 发起异步的远程调用(rpc)
|
||||||
let randomEvent = randomBytes(16).toString('hex')
|
let randomEvent = randomBytes(16).toString('hex')
|
||||||
// console.log('randomEvent is randomized: ', randomEvent)
|
// console.log('randomEvent is randomized: ', randomEvent)
|
||||||
if ( typeof(ack) === 'function' ){ // 有回调
|
if (typeof ack === 'function') {
|
||||||
this.send(JSON.stringify({type:'REQUEST', rpc, param, randomEvent}), ()=>{
|
// 有回调
|
||||||
// console.log('in callback, randomEvent=', randomEvent)
|
this.send(JSON.stringify({ type: 'REQUEST', rpc, param, randomEvent }), () => {
|
||||||
|
// console.log('in callback, randomEvent=', randomEvent)
|
||||||
this.once(randomEvent, ack)
|
this.once(randomEvent, ack)
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
if (this.eventNames().indexOf(randomEvent)>=0){
|
if (this.eventNames().indexOf(randomEvent) >= 0) {
|
||||||
this.removeAllListeners(randomEvent)
|
this.removeAllListeners(randomEvent)
|
||||||
ack({_state:'timeout', error:'timeout happens'})
|
ack({ _state: 'timeout', error: 'timeout happens' })
|
||||||
}
|
}
|
||||||
}, timeout)
|
}, timeout)
|
||||||
})
|
})
|
||||||
} else { // 没有回调
|
} else {
|
||||||
return new Promise((resolve, reject)=>{
|
// 没有回调
|
||||||
this.send(JSON.stringify({type:'REQUEST', rpc, param, randomEvent}), ()=>{
|
return new Promise((resolve, reject) => {
|
||||||
|
this.send(JSON.stringify({ type: 'REQUEST', rpc, param, randomEvent }), () => {
|
||||||
this.once(randomEvent, resolve)
|
this.once(randomEvent, resolve)
|
||||||
setTimeout(()=>{
|
setTimeout(() => {
|
||||||
if (this.eventNames().indexOf(randomEvent)>=0){
|
if (this.eventNames().indexOf(randomEvent) >= 0) {
|
||||||
this.removeAllListeners(randomEvent)
|
this.removeAllListeners(randomEvent)
|
||||||
resolve({_state:'timeout', error:'timeout happens'})
|
resolve({ _state: 'timeout', error: 'timeout happens' })
|
||||||
}
|
}
|
||||||
}, timeout)
|
}, timeout)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
onMessage(){ // 接收到远程消息
|
|
||||||
this.onmessage = async ({data})=>{ // 不能直接定义成一个函数,而要现场赋值。因为里面用到了 this 还是指向 ws.prototype 而不是socket本身
|
|
||||||
// console.log('onmessage 被调用')
|
|
||||||
try {
|
|
||||||
let obj = JSON.parse(data)
|
|
||||||
// console.log('message data parsed to obj=',obj)
|
|
||||||
switch (obj.type) {
|
|
||||||
case 'NOTIFY': // 接收到同步的远程调用
|
|
||||||
// console.log(`NOTIFY message: rpc=${obj.rpc}, param=${JSON.stringify(obj.param)}`)
|
|
||||||
if (this.hasOwnProperty(obj.rpc)) // 作为rpc调用
|
|
||||||
this[obj.rpc](obj.param)
|
|
||||||
else if (this.eventNames().indexOf(obj.rpc)>=0) // 作为event调用
|
|
||||||
this.emit(obj.rpc, obj.param)
|
|
||||||
else
|
|
||||||
console.log('onmessage unknown notification')
|
|
||||||
case 'REQUEST': // 接收到异步的远程调用
|
|
||||||
// console.log(`被动方 收到 REQUEST: rpc=${obj.rpc}, param=${JSON.stringify(obj.param)}`)
|
|
||||||
let result
|
|
||||||
if (this.hasOwnProperty(obj.rpc)) {
|
|
||||||
result = await this[obj.rpc](obj.param)
|
|
||||||
}else {
|
|
||||||
result = {_state:'error', error:'unknown rpc'}
|
|
||||||
}
|
|
||||||
if (obj.randomEvent){
|
|
||||||
this.send(JSON.stringify({type:'REPLY', randomEvent: obj.randomEvent, result})) // 返回结果给远程
|
|
||||||
}
|
|
||||||
case 'REPLY': // 接收到远程返回的结果
|
|
||||||
// console.log('主动方 收到 REPLY: result=', obj.result)
|
|
||||||
this.emit(obj.randomEvent, obj.result)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}catch(exception){
|
|
||||||
console.error('Invalid socket message received!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// (async ()=>{
|
// (async ()=>{
|
||||||
|
|
||||||
// new TicSocket('http://localhost:9007')
|
// new RpcSocket('http://localhost:9007')
|
||||||
// await sleep(20000)
|
// await sleep(20000)
|
||||||
// new TicSocket.Server({port:9007})
|
// new RpcSocket.Server({port:9007})
|
||||||
// await sleep(20000)
|
// await sleep(20000)
|
||||||
|
|
||||||
// })()
|
// })()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
//TicSocket=require('./Ling/TicSocket.js');
|
//RpcSocket=require('./Ling/RpcSocket.js');
|
||||||
server = new TicSocket.Server({port:6000});
|
server = new RpcSocket.Server({port:6000});
|
||||||
var serverSocket; server.on('connection', (socket)=>{console.log('socket coming');
|
var serverSocket; server.on('connection', (socket)=>{console.log('socket coming');
|
||||||
serverSocket = TicSocket.upgrade(socket).on('close', (code, reason)=>console.log('socket is closed for code and reason: ', code, reason))
|
serverSocket = RpcSocket.upgrade(socket).on('close', (code, reason)=>console.log('socket is closed for code and reason: ', code, reason))
|
||||||
.on('error', (errer)=>console.log('socket has error: ', error))
|
.on('error', (errer)=>console.log('socket has error: ', error))
|
||||||
})
|
})
|
||||||
|
|
||||||
TicSocket.connectAsync('http://localhost:6000').then((clientSocket)=>{
|
RpcSocket.connectAsync('http://localhost:6000').then((clientSocket)=>{
|
||||||
clientSocket.request('testfunc', {height:99}, (result)=>console.log('using request: ', result), 3000)
|
clientSocket.request('testfunc', {height:99}, (result)=>console.log('using request: ', result), 3000)
|
||||||
return clientSocket
|
return clientSocket
|
||||||
}).then((clientSocket)=>{
|
}).then((clientSocket)=>{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "websocket",
|
"name": "so.rpcsocket",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
Loading…
Reference in New Issue
Block a user