这是基于vue-vben-admin 模板适用于abp Vnext的前端管理项目
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

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,
};
}