fix: defer exec error

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2019-06-30 17:01:50 +08:00
parent f9f59c6ba2
commit 6491df2ed4
5 changed files with 48 additions and 26 deletions

View File

@ -11,8 +11,8 @@ export class Namespace extends interfaces.Namespace {
public async connection(socket: io.Socket) { public async connection(socket: io.Socket) {
console.log(this.nsp.name, socket.id, 'connection'); console.log(this.nsp.name, socket.id, 'connection');
this.defer(socket => console.log(this.nsp.name, socket.id, 'defer', this)) this.defer(socket, socket => console.log(this.nsp.name, socket.id, 'defer', this))
return `Welcome to Websocket Chat Room Now: ${Date.now()} Your ID: ${socket.id}! \n`; return `Welcome to Websocket Chat Room Now: ${Date.now()} Your ID: ${socket.id}! \r\n`;
} }
public async disconnect(socket: io.Socket) { public async disconnect(socket: io.Socket) {
@ -28,8 +28,7 @@ export class Namespace extends interfaces.Namespace {
this.cache[socket.id] = (this.cache[socket.id] || '') + data; this.cache[socket.id] = (this.cache[socket.id] || '') + data;
if (data == '\r' && this.cache[socket.id] !== "") { if (data == '\r' && this.cache[socket.id] !== "") {
let result = new BroadcastMessage(this.cache[socket.id] + '\n') let result = new BroadcastMessage(this.cache[socket.id] + '\n')
this.cache[socket.id] = ''; return delete this.cache[socket.id] && result;
return result;
} }
return data; return data;
} }

View File

@ -1,9 +1,9 @@
import "reflect-metadata"; import "reflect-metadata";
import * as io from 'socket.io' import * as io from 'socket.io'
import { Container } from 'inversify' import { Container } from 'inversify'
import { TYPE } from './constants' import { TYPE, METADATA_KEY } from './constants'
import { interfaces, Message, BroadcastMessage } from './interfaces' import { interfaces, Message, BroadcastMessage, EventMessage } from './interfaces'
import { getNamespaces, getNamespaceMetadata, getNamespaceListenerMetadata } from './utils' import { getNamespaces, getNamespaceMetadata, getNamespaceListenerMetadata, getSocketDeferMetadata } from './utils'
export function buildWebSocket(container: Container, server: io.Server) { export function buildWebSocket(container: Container, server: io.Server) {
let constructors = getNamespaces(); let constructors = getNamespaces();
@ -12,13 +12,11 @@ export function buildWebSocket(container: Container, server: io.Server) {
registryNamespace(container, constructors); registryNamespace(container, constructors);
// get all namespaces // get all namespaces
let namespaces = container.getAll<interfaces.Namespace>(TYPE.Namespace) let namespaces = container.getAll<interfaces.Namespace>(TYPE.Namespace);
for (const namespace of namespaces) { for (const namespace of namespaces) {
let namespaceMetadata = getNamespaceMetadata(namespace); let namespaceMetadata = getNamespaceMetadata(namespace);
let namespaceEventMetadata = getNamespaceListenerMetadata(namespace); let namespaceEventMetadata = getNamespaceListenerMetadata(namespace);
let ns = server.of(namespaceMetadata.name); let ns = initNamespace(server, namespaceMetadata, namespace);
namespace.constructor.prototype.nsp = ns;
applyNamespaceMiddleware(namespaceMetadata, ns);
ns.on('connection', async (socket: io.Socket) => { ns.on('connection', async (socket: io.Socket) => {
let namespaceInstance = container.getNamed<interfaces.Namespace>(TYPE.Namespace, namespace.constructor.name); let namespaceInstance = container.getNamed<interfaces.Namespace>(TYPE.Namespace, namespace.constructor.name);
await applyEvent(namespaceInstance, socket); await applyEvent(namespaceInstance, socket);
@ -39,6 +37,14 @@ function registryNamespace(container: Container, constructors: any[]) {
.whenTargetNamed(name); .whenTargetNamed(name);
}); });
} }
function initNamespace(server: io.Server, namespaceMetadata: interfaces.NamespaceMetadata, namespace: interfaces.Namespace) {
let ns = server.of(namespaceMetadata.name);
namespace.constructor.prototype.nsp = ns;
applyNamespaceMiddleware(namespaceMetadata, ns);
return ns;
}
function applyNamespaceMiddleware(namespaceMetadata: interfaces.NamespaceMetadata, ns: io.Namespace) { function applyNamespaceMiddleware(namespaceMetadata: interfaces.NamespaceMetadata, ns: io.Namespace) {
for (const middleware of namespaceMetadata.middleware) { for (const middleware of namespaceMetadata.middleware) {
ns.use(middleware); ns.use(middleware);
@ -53,6 +59,7 @@ function flatten(arr: Array<any>) {
} }
function applyMiddlewares(namespaceEventMetadata: interfaces.ListenerMetadata[], socket: io.Socket) { function applyMiddlewares(namespaceEventMetadata: interfaces.ListenerMetadata[], socket: io.Socket) {
// flatten all event middleware and apply
let middlewares = [...new Set(flatten(namespaceEventMetadata.map((data) => data.middleware)))]; let middlewares = [...new Set(flatten(namespaceEventMetadata.map((data) => data.middleware)))];
for (const middleware of middlewares) { for (const middleware of middlewares) {
socket.use((packet: io.Packet, next: (err?: any) => void) => { middleware(socket, packet, next); }); socket.use((packet: io.Packet, next: (err?: any) => void) => { middleware(socket, packet, next); });
@ -60,14 +67,19 @@ function applyMiddlewares(namespaceEventMetadata: interfaces.ListenerMetadata[],
} }
async function applyEvent(namespaceInstance: interfaces.Namespace, socket: io.Socket) { async function applyEvent(namespaceInstance: interfaces.Namespace, socket: io.Socket) {
// init socket defer array
Reflect.defineMetadata(METADATA_KEY.defer, [], socket);
// apply connection event
if (namespaceInstance.connection) { if (namespaceInstance.connection) {
let result = await namespaceInstance.connection(socket); let result = await namespaceInstance.connection(socket);
if (result != undefined) { if (result != undefined) {
socket.send(result); socket.send(result);
} }
} }
// apply disconnect event
socket.on('disconnect', async () => { socket.on('disconnect', async () => {
await namespaceInstance.defers.forEach(defer => defer(socket)); // exec defer function
getSocketDeferMetadata(socket).forEach(defer => defer(socket));
if (namespaceInstance.disconnect) { if (namespaceInstance.disconnect) {
await namespaceInstance.disconnect(socket); await namespaceInstance.disconnect(socket);
} }
@ -79,12 +91,12 @@ function applyListeners(namespaceEventMetadata: interfaces.ListenerMetadata[], s
socket.on(event.name, async data => { socket.on(event.name, async data => {
let result = await namespaceInstance[event.key](socket, data); let result = await namespaceInstance[event.key](socket, data);
if (result != undefined) { if (result != undefined) {
if (result instanceof Message) {
if (result instanceof BroadcastMessage) { if (result instanceof BroadcastMessage) {
socket.broadcast.emit(result.event || event.name, result.message); socket.broadcast.emit(result.event || event.name, result.message);
} else { } else if (result instanceof EventMessage) {
socket.emit(result.event || event.name, result.message); socket.emit(result.event || event.name, result.message);
} } else if (result instanceof Message) {
socket.emit(result.event || 'message', result.message);
} else { } else {
socket.emit(event.name, result); socket.emit(event.name, result);
} }

View File

@ -5,5 +5,6 @@ export const TYPE = {
export const METADATA_KEY = { export const METADATA_KEY = {
namespace: "@cc-server/ws:namespace", namespace: "@cc-server/ws:namespace",
listener: "@cc-server/ws:listener" listener: "@cc-server/ws:listener",
defer: "@cc-server/ws:defer"
}; };

View File

@ -1,23 +1,24 @@
import * as io from 'socket.io' import * as io from 'socket.io'
import { injectable } from 'inversify'; import { injectable } from 'inversify';
import { getSocketDeferMetadata } from './utils'
export class Message { export class Message {
constructor(public message: any, public event?: string) { } constructor(public message: any, public event?: string) { }
} }
export class EventMessage extends Message {
}
export class BroadcastMessage extends Message { export class BroadcastMessage extends Message {
} }
export namespace interfaces { export namespace interfaces {
export type SocketEvent = ((socket: io.Socket) => void);
@injectable() @injectable()
export class Namespace { export class Namespace {
/** /**
* @see io.Namespace * @see io.Namespace
*/ */
public nsp?: io.Namespace; public nsp?: io.Namespace;
/**
* Defer Functions Array
*/
public defers?: ((socket: io.Socket) => void)[] = [];
/** /**
* The event fired when we get a new connection * The event fired when we get a new connection
* @param socket socket * @param socket socket
@ -32,8 +33,8 @@ export namespace interfaces {
/** /**
* add disconnect defer function * add disconnect defer function
*/ */
protected defer?(fn: (socket: io.Socket) => void) { protected defer?(socket: io.Socket, fn: SocketEvent) {
this.defers.push(fn); getSocketDeferMetadata(socket).unshift(fn);
} }
/** /**
* Event Listener * Event Listener

View File

@ -29,9 +29,18 @@ function getNamespaceListenerMetadata(target: any) {
return eventMetadata; return eventMetadata;
} }
function getSocketDeferMetadata(target: any) {
let socketDeferMetadata: interfaces.SocketEvent[] = Reflect.getMetadata(
METADATA_KEY.defer,
target
) || [];
return socketDeferMetadata;
}
export { export {
getNamespaces, getNamespaces,
getNamespaceMetadata, getNamespaceMetadata,
getNamespacesMetadata, getNamespacesMetadata,
getNamespaceListenerMetadata getNamespaceListenerMetadata,
getSocketDeferMetadata
} }