You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
3.9 KiB
154 lines
3.9 KiB
import { onMounted, onUnmounted } from 'vue';
|
|
import {
|
|
HubConnection,
|
|
HubConnectionBuilder,
|
|
HubConnectionState,
|
|
IHttpConnectionOptions,
|
|
LogLevel,
|
|
} from '@microsoft/signalr';
|
|
import { useUserStoreWithOut } from '/@/store/modules/user';
|
|
|
|
import mitt from '/@/utils/mitt';
|
|
|
|
interface SignalROptions {
|
|
serverUrl: string;
|
|
autoStart?: boolean;
|
|
useAccessToken?: boolean;
|
|
automaticReconnect?: boolean;
|
|
nextRetryDelayInMilliseconds?: number;
|
|
}
|
|
|
|
interface UseSignalR {
|
|
lazyInit?: boolean;
|
|
}
|
|
|
|
export function useSignalR(options: UseSignalR & SignalROptions) {
|
|
const emitter = mitt();
|
|
let connection: HubConnection | null = null;
|
|
|
|
onMounted(() => {
|
|
!options.lazyInit && init(options);
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
if (connection !== null && connection.state === HubConnectionState.Connected) {
|
|
stop();
|
|
}
|
|
});
|
|
|
|
function init({
|
|
serverUrl,
|
|
autoStart = false,
|
|
useAccessToken = true,
|
|
automaticReconnect = true,
|
|
nextRetryDelayInMilliseconds = 60000,
|
|
}: SignalROptions) {
|
|
const httpOptions: IHttpConnectionOptions = {};
|
|
if (useAccessToken) {
|
|
const userStore = useUserStoreWithOut();
|
|
const token = userStore.getToken;
|
|
httpOptions.accessTokenFactory = () =>
|
|
token.startsWith('Bearer ') ? token.substring(7) : token;
|
|
}
|
|
const connectionBuilder = new HubConnectionBuilder()
|
|
.withUrl(serverUrl, httpOptions)
|
|
.configureLogging(LogLevel.Warning);
|
|
if (automaticReconnect && nextRetryDelayInMilliseconds) {
|
|
connectionBuilder.withAutomaticReconnect({
|
|
nextRetryDelayInMilliseconds: () => nextRetryDelayInMilliseconds,
|
|
});
|
|
}
|
|
connection = connectionBuilder.build();
|
|
if (autoStart) {
|
|
start();
|
|
}
|
|
}
|
|
|
|
async function start(): Promise<void> {
|
|
if (connection == null) {
|
|
return Promise.reject('unable to start, connection not initialized!');
|
|
}
|
|
emitter.emit('signalR:beforeStart');
|
|
try {
|
|
await connection.start();
|
|
emitter.emit('signalR:onStart');
|
|
} catch (error) {
|
|
emitter.emit('signalR:onError', error);
|
|
}
|
|
}
|
|
|
|
async function stop(): Promise<void> {
|
|
if (connection == null) {
|
|
return Promise.reject('unable to stop, connection not initialized!');
|
|
}
|
|
emitter.emit('signalR:beforeStop');
|
|
try {
|
|
await connection.stop();
|
|
emitter.emit('signalR:onStop');
|
|
} catch (error) {
|
|
emitter.emit('signalR:onError', error);
|
|
}
|
|
}
|
|
|
|
function beforeStart<T = any>(callback: (event?: T) => void) {
|
|
emitter.on('signalR:beforeStart', callback);
|
|
}
|
|
|
|
function onStart<T = any>(callback: (event?: T) => void) {
|
|
emitter.on('signalR:onStart', callback);
|
|
}
|
|
|
|
function beforeStop<T = any>(callback: (event?: T) => void) {
|
|
emitter.on('signalR:beforeStop', callback);
|
|
}
|
|
|
|
function onStop<T = any>(callback: (event?: T) => void) {
|
|
emitter.on('signalR:onStop', callback);
|
|
}
|
|
|
|
function onError(callback: (error?: Error) => void) {
|
|
emitter.on('signalR:onError', callback);
|
|
}
|
|
|
|
function on(methodName: string, newMethod: (...args: any[]) => void): void {
|
|
connection?.on(methodName, newMethod);
|
|
}
|
|
|
|
function off(methodName: string, method: (...args: any[]) => void): void {
|
|
connection?.off(methodName, method);
|
|
}
|
|
|
|
function onClose(callback: (error?: Error) => void): void {
|
|
connection?.onclose(callback);
|
|
}
|
|
|
|
function send(methodName: string, ...args: any[]): Promise<void> {
|
|
if (connection == null) {
|
|
return Promise.reject('unable to send message, connection not initialized!');
|
|
}
|
|
return connection.send(methodName, ...args);
|
|
}
|
|
|
|
function invoke<T = any>(methodName: string, ...args: any[]): Promise<T> {
|
|
if (connection == null) {
|
|
return Promise.reject('unable to send message, connection not initialized!');
|
|
}
|
|
return connection.invoke(methodName, ...args);
|
|
}
|
|
|
|
return {
|
|
on,
|
|
off,
|
|
init,
|
|
onError,
|
|
onClose,
|
|
beforeStart,
|
|
onStart,
|
|
beforeStop,
|
|
onStop,
|
|
send,
|
|
invoke,
|
|
start,
|
|
stop,
|
|
};
|
|
}
|
|
|