diff --git a/src/services/signalr/index.ts b/src/services/signalr/index.ts index dc5f358..5a8ed93 100755 --- a/src/services/signalr/index.ts +++ b/src/services/signalr/index.ts @@ -1,6 +1,9 @@ import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr' import { getUserToken, isDev } from '@utils' +import { makeTaskQueue } from '@utils/queue' + +const queue = makeTaskQueue() // SignalR js api: //https://docs.microsoft.com/ru-ru/javascript/api/@aspnet/signalr/?view=signalr-js-latest @@ -53,7 +56,7 @@ const MakeUnsubscribeFunction = ( connection: HubConnection, groupName: string[] | string | null, ...groups: SubscribeGroup[] -): cleanFunction => async() => { +): cleanFunction => () => queue.push(async() => { if(connection.state === HubConnectionState.Connected) { if (groupName) { if (Array.isArray(groupName)) { @@ -64,8 +67,8 @@ const MakeUnsubscribeFunction = ( for (const g of groups) connection.off(g.methodName) } - connection.stop() -} + await connection.stop() +}) /** Subscribe on some SignalR method (topic). * @example useEffect(() => SubscribeMultiple('/url/', `${id}`, { methodName: 'methodName', handler: handleNewData }), [id]); @@ -78,17 +81,19 @@ export const Subscribe = ( groupName: string[] | string = '', ...groups: SubscribeGroup[] ): cleanFunction => { - GetConnectionAsync(hubUrl).then(async connection => { - if (groupName) { - if (Array.isArray(groupName)) { - for (const g of groupName) - await connection.send('AddToGroup', g) - } else await connection.send('AddToGroup', groupName) - } - for (const g of groups) - connection.on(g.methodName, g.handler) + queue.push(async () => { + await GetConnectionAsync(hubUrl).then(async connection => { + if (groupName) { + if (Array.isArray(groupName)) { + for (const g of groupName) + await connection.send('AddToGroup', g) + } else await connection.send('AddToGroup', groupName) + } + for (const g of groups) + connection.on(g.methodName, g.handler) + }) }) - + return MakeUnsubscribeFunction(Connections[hubUrl], groupName, ...groups) } diff --git a/src/utils/queue.ts b/src/utils/queue.ts new file mode 100644 index 0000000..cebc32e --- /dev/null +++ b/src/utils/queue.ts @@ -0,0 +1,28 @@ +export type TaskHandler = () => T | PromiseLike + +export type Queue = { + push: (task: TaskHandler) => Promise + readonly length: number +} + +export const makeTaskQueue = (): Queue => { + let pending: Promise = Promise.resolve() + let count: number = 0 + + const run = async (task?: TaskHandler) => { + count++ + try { + await pending; + } finally { + count-- + return Promise.resolve().then(task); + } + } + + return { + push: (task: TaskHandler) => pending = run(task), + length: count, + } +} + +export default makeTaskQueue