All Projects → Odonno → ngrx-signalr-core

Odonno / ngrx-signalr-core

Licence: MIT License
A library to handle realtime SignalR (.NET Core) events using @angular, rxjs and the @ngrx library

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to ngrx-signalr-core

Taskmgr
a team collaboration tutorial app like teambition/worktile
Stars: ✭ 95 (+427.78%)
Mutual labels:  rxjs, ngrx
ts-action-operators
TypeScript action operators for NgRx and redux-observable
Stars: ✭ 34 (+88.89%)
Mutual labels:  rxjs, ngrx
Example App
Example app showcasing the ngrx platform
Stars: ✭ 1,361 (+7461.11%)
Mutual labels:  rxjs, ngrx
TypedSignalR.Client
C# Source Generator to Create Strongly Typed SignalR Client.
Stars: ✭ 16 (-11.11%)
Mutual labels:  signalr, signalr-core
SignalR-Core-SqlTableDependency
Shows how the new SignalR Core works with hubs and sockets, also how it can integrate with SqlTableDependency API.
Stars: ✭ 36 (+100%)
Mutual labels:  signalr, signalr-core
Ngrx Ducks
Improved Coding Experience for NgRx
Stars: ✭ 56 (+211.11%)
Mutual labels:  rxjs, ngrx
Router Store
Bindings to connect the Angular Router to @ngrx/store
Stars: ✭ 187 (+938.89%)
Mutual labels:  rxjs, ngrx
Angularfire
The official Angular library for Firebase.
Stars: ✭ 7,029 (+38950%)
Mutual labels:  rxjs, ngrx
kanban-project-management
Web Application to manage software development projects.
Stars: ✭ 39 (+116.67%)
Mutual labels:  rxjs, ngrx
community-events-angular
Community Events App built with ❤️ using Angular, NgRx, Rxjs to do thrill in #hacktoberfest21
Stars: ✭ 20 (+11.11%)
Mutual labels:  rxjs, ngrx
signalr-client
SignalR client library built on top of @aspnet/signalr. This gives you more features and easier to use.
Stars: ✭ 48 (+166.67%)
Mutual labels:  rxjs, signalr
juliette
Reactive State Management Powered by RxJS
Stars: ✭ 84 (+366.67%)
Mutual labels:  rxjs, ngrx
Angular Ngrx Data
Angular with ngRx and experimental ngrx-data helper
Stars: ✭ 954 (+5200%)
Mutual labels:  rxjs, ngrx
Game Music Player
All your music are belong to us
Stars: ✭ 76 (+322.22%)
Mutual labels:  rxjs, ngrx
Platform
Reactive libraries for Angular
Stars: ✭ 7,020 (+38900%)
Mutual labels:  rxjs, ngrx
Angular Rpg
RPG game built with Typescript, Angular, ngrx/store and rxjs
Stars: ✭ 120 (+566.67%)
Mutual labels:  rxjs, ngrx
Soundcloud Ngrx
SoundCloud API client with Angular • RxJS • ngrx/store • ngrx/effects
Stars: ✭ 438 (+2333.33%)
Mutual labels:  rxjs, ngrx
Angular Learning Resources
Curated chronological list of learning resources for Angular, from complete beginner to advanced level
Stars: ✭ 615 (+3316.67%)
Mutual labels:  rxjs, ngrx
streamkit
My streaming overlay platform for YouTube https://bit.ly/3AvaoFz and Twitch https://bit.ly/37xUPAM
Stars: ✭ 15 (-16.67%)
Mutual labels:  rxjs, ngrx
angular2-instagram
🔥Instagram like photo filter playground built with Angular2 (Web | Desktop)
Stars: ✭ 91 (+405.56%)
Mutual labels:  rxjs, ngrx

ngrx-signalr-core

A library to handle realtime SignalR (.NET Core) events using angular, rxjs and the @ngrx library.

This library is made for the SignalR client using .NET Core. If you need to target .NET Framework, please check this repository : https://github.com/Odonno/ngrx-signalr

Get started

Install dependencies

npm install rxjs @ngrx/store @ngrx/effects @microsoft/signalr --save
npm install ngrx-signalr-core --save

Once everything is installed, you can use the reducer and the effects inside the AppModule.

@NgModule({
    ...,
    imports: [
        StoreModule.forRoot({ signalr: signalrReducer }),
        EffectsModule.forRoot([SignalREffects, AppEffects])
    ],
    ...
})
export class AppModule { }
Start with a single Hub...

First, you will start the application by dispatching the creation of one Hub.

// TODO : your hub definition
const hub = {
  hubName: "hub name",
  url: "https://localhost/path",
};

this.store.dispatch(createSignalRHub(hub));

Then you will create an effect to start listening to events before starting the Hub.

initRealtime$ = createEffect(() =>
  this.actions$.pipe(
    ofType(SIGNALR_HUB_UNSTARTED),
    mergeMapHubToAction(({ hub }) => {
      // TODO : add event listeners
      const whenEvent$ = hub.on("eventName").pipe(map((x) => createAction(x)));

      return merge(whenEvent$, of(startSignalRHub(hub)));
    })
  )
);

You can also send events at anytime.

sendEvent$ = createEffect(() =>
  this.actions$.pipe(
    ofType(SEND_EVENT), // TODO : create a custom action
    mergeMap(({ params }) => {
      const hub = findHub(timeHub);
      if (!hub) {
        return of(hubNotFound(timeHub));
      }

      // TODO : send event to the hub
      return hub.send("eventName", params).pipe(
        map((_) => sendEventFulfilled()),
        catchError((error) => of(sendEventFailed(error)))
      );
    })
  )
);
...or use multiple Hubs

Now, start with multiple hubs at a time.

// simplified hub creation
const dispatchHubCreation = (hub) => this.store.dispatch(createSignalRHub(hub));

const hub1 = {}; // define hubName and url
const hub2 = {}; // define hubName and url
const hub3 = {}; // define hubName and url

dispatchHubCreation(hub1);
dispatchHubCreation(hub2);
dispatchHubCreation(hub3);

You will then initialize your hubs in the same way but you need to know which one is initialized.

const hub1 = {}; // define hubName and url
const hub2 = {}; // define hubName and url

initHubOne$ = createEffect(() =>
  this.actions$.pipe(
    ofType(SIGNALR_HUB_UNSTARTED),
    ofHub(hub1),
    mergeMapHubToAction(({ action, hub }) => {
      // TODO : init hub 1
    })
  )
);

initHubTwo$ = createEffect(() =>
  this.actions$.pipe(
    ofType(SIGNALR_HUB_UNSTARTED),
    ofHub(hub2),
    mergeMapHubToAction(({ action, hub }) => {
      // TODO : init hub 2
    })
  )
);

And then you can start your app when all hubs are connected the first time.

appStarted$ = createEffect(() =>
  this.store.pipe(
    select(selectAreAllHubsConnected),
    filter((areAllHubsConnected) => !!areAllHubsConnected),
    first(),
    map((_) => of(appStarted())) // TODO : create a custom action when hubs are connected
  )
);
Handling reconnection

Since .NET Core, you need to handle the SignalR Hub reconnection by yourself. Here is an example on how to apply periodic reconnection:

// try to reconnect all hubs every 10s (when the navigator is online)
whenDisconnected$ = createReconnectEffect(this.actions$);

In this example, we did not use a custom reconnection policy. So the default behavior will automatically be to apply a periodic reconnection attempt every 10 seconds when the hub is disconnected and when there is a network connection.

Of course, you can write your own reconnectionPolicy inside the options of the function, so you have the benefit to write your own reconnection pattern (periodic retry, exponential retry, etc..).

You can also filter by hubName so that it will affect only one hub.

API features

SignalR Hub

The SignalR Hub is an abstraction of the hub connection. It contains function you can use to:

  • start the connection
  • listen to events emitted
  • send a new event
interface ISignalRHub {
  hubName: string;
  url: string;
  options: IHttpConnectionOptions | undefined;

  start$: Observable<void>;
  stop$: Observable<void>;
  state$: Observable<string>;
  error$: Observable<Error | undefined>;

  constructor(
    hubName: string,
    url: string,
    options: IHttpConnectionOptions | undefined
  );

  start(): Observable<void>;
  stop(): Observable<void>;
  on<T>(eventName: string): Observable<T>;
  off(eventName: string): void;
  stream<T>(methodName: string, ...args: any[]): Observable<T>;
  send<T>(methodName: string, ...args: any[]): Observable<T>;
  sendStream<T>(methodName: string, subject: Subject<T>): Observable<void>;
  hasSubscriptions(): boolean;
}

You can find an existing hub by its name and url.

function findHub(hubName: string, url: string): ISignalRHub | undefined;
function findHub({
  hubName,
  url,
}: {
  hubName: string;
  url: string;
}): ISignalRHub | undefined;

And create a new hub.

function createHub(
  hubName: string,
  url: string,
  options: IHttpConnectionOptions | undefined
): ISignalRHub | undefined;
State

The state contains all existing hubs that was created with their according status (unstarted, connected, disconnected).

const unstarted = "unstarted";
const connected = "connected";
const disconnected = "disconnected";

type SignalRHubState =
  | typeof unstarted
  | typeof connected
  | typeof disconnected;

type SignalRHubStatus = {
  hubName: string;
  url: string;
  state: SignalRHubState;
};
class BaseSignalRStoreState {
  hubStatuses: SignalRHubStatus[];
}
Actions

Actions to dispatch

createSignalRHub will initialize a new hub connection but it won't start the connection so you can create event listeners.

const createSignalRHub = createAction(
  "@ngrx/signalr/createHub",
  props<{
    hubName: string;
    url: string;
    options?: IHttpConnectionOptions | undefined;
  }>()
);

startSignalRHub will start the hub connection so you can send and receive events.

const startSignalRHub = createAction(
  "@ngrx/signalr/startHub",
  props<{ hubName: string; url: string }>()
);

stopSignalRHub will stop the current hub connection.

const stopSignalRHub = createAction(
  "@ngrx/signalr/stopHub",
  props<{ hubName: string; url: string }>()
);

reconnectSignalRHub will give you a way to reconnect to the hub.

const reconnectSignalRHub = createAction(
  "@ngrx/signalr/reconnectHub",
  props<{ hubName: string; url: string }>()
);

hubNotFound can be used when you do retrieve your SignalR hub based on its name and url.

export const hubNotFound = createAction(
  "@ngrx/signalr/hubNotFound",
  props<{ hubName: string; url: string }>()
);
Effects
// create hub automatically
createHub$;
// listen to start result (success/fail)
// listen to change connection state (connecting, connected, disconnected, reconnecting)
// listen to hub error
beforeStartHub$;
// start hub automatically
startHub$;
// stop hub
stopHub$;
Selectors
// used to select all hub statuses in state
const hubStatuses$ = store.pipe(select(selectHubsStatuses));

// used to select a single hub status based on its name and url
const hubStatus$ = store.pipe(select(selectHubStatus, { hubName, url }));

// used to know if all hubs are connected
const areAllHubsConnected$ = store.pipe(select(selectAreAllHubsConnected));

// used to know when a hub is in a particular state
const hasHubState$ = store.pipe(
  select(selectHasHubState, { hubName, url, state })
);
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].