Hello guys ! Here is an image of my "issue" ! I'm trying to find how I could link my GameService instance with the websocket, because I need to add methods on both sides ( GameService calling socketNamespace.emit and socketNamespace.on calling GameService methods ), and so, as I wanted to avoid circular imports ( I think we care about that right ? ), I'm currently trying to find a solution for this kind of use case, how could I resolve that and link my GameService to the socket IO namespace properly ?
Hope you guys can help ! That would be really amazing ! π
#Socket IO interactions with Express and Service/Controller
1 messages Β· Page 1 of 1 (latest)
I suggest using rxjs :)
Uh ? What is this ?
And how could that be usefull in this case ?
You can use a Subject provided to both modules and avoid a circular reference.
Isnt that the same concept / system than using an event emitter ? This is almost the same no ?
Subjects fill a similar role, but can utilise the whole rxjs ecosystem, making them a lot more flexible than EE, with a lot more control
Every incoming connection can be an observable that you can push to a subject, all while consuming ends can use filter, map etc to get their required state data
Kk it seems a bit complicated but I'll have a look and try to understand how it works and how I can implement this in my project
2 other questions :
If I want to do that without using Event Emitter / RxJS, IS there any other way to do it than passing the ws to the service constructor ? ( Or in the other way, create the socket events / namespace inside of my constructor so I can access both socket and service
And last one, is that a good thing to use functions to create my websockets + his events / namespaces, for exemple, adding to my main file :
const io = createWebSocket(server)
And in createWebSocket I do like
const io = new Server(server)
io.on('connected', (socket) => {
registerEvents(io, socket)
})
return io
- no, it's why we need a mediator of some sorts. It's also bad form for a service to control an unrelated socket for example.
- yes! This is called a factory function, and is a very useful pattern
-
Kk so it is way better having some sort of event emitter to manage interactions between websocket and controllers / services ?
-
Then, as my websocket will be defined with this, my service will not be called anywhere, so, should I create a files importing all my services to the main file / process to init these ?
Or where / how should I import / init my services if they are not being used by the routes ? ( And so they are not imported to my app)
π
Idk if there's a better way to do that or...
It's hard to respond to number 2 without knowing what your GameService does
It is basically a service that is listening events from a game client ( League of Legends here ), and fetching data every Xs, then formatting / treating the data to send it to the websocket / emitter so it can be sent to the client to update the opened pages
Here is the code I have rn, I just need to add the emit / send data to the emitter / websocket, and add connection to the game client socket to listen to events
But this is basically the code I have rn
This is the code of my service rn, and I might have a few like this one
And I don't really know where / how I should init these services in my project, to create the instance of the service and so make it enable / available
Generally this is what an index.js is for, composing application component instances
Kk so yep I should write an index file initiating all my services and import it to the global index ?
index.ts
import './services'
services/index.ts
import { LeagueService } from './league'
// Other services imports
new LeagueService()
// Other services instances
```
Something like that ig ?
No, I would compose it in the root level index.
So add the
new LeagueService()
In the main index.ts ?
But what if I have a lot of services to init ? ( 8/10 )
That's why I was thinking about adding those inside a specific index file just for services
But basically that's the same thing
I need to import my services like this and just run new Service() in my index file right ?
π
The way I prefer to do it is this in a more traditional codebade:
- /some-feature/service.ts
export const SomeService = (deps: Deps) => ({})
-
/other-feature/service.ts
// similar -
/services.ts
export function getSomeService () {
return isProduction()
? SomeService({ whatever, deps })
: DevelopmentSomeService({ wevs })
}
/* etc*/
- /index.ts
function main () {
const someService = getSomeService()
const someDependentComponent = SomeDependentComponent({ someDependentComponent })
}
main()
kk, would you wrap the service in a function rather than in a class ?
And so, if I look at what you sait, should I pass the Event Emitter / RxJS observable inside the deps or is it fine importing it directly in service.ts ?
π
Also last question, could I do a global function to start my services like
services.ts
export function runServices() {
const service = getSomeService()
const service2 = = getOtherService()
// etc ...
}
And just call this in my main.ts if I don't need my services inside of it as variables ?
idk if its fine doing like that or no
Oh I mean that's a preference thing. I prefer to do that, you don't need to.
The idea is that if something depends on the services you can pass that to them
kk I see
Thx a lot for your help
So, I was finally able to make it works, but now I have one issue
My service is running, and it has a variable / property service.status ( active, starting, inactive )
When the client connect to the service, I would like the client to be able to retrieve the current status ( then, after that, the client will receive status updates from websocket )
How could I manage to give the user the first status when he open my page ( react app ) ? Should I use an http request or socket message may be ?
Ironically there is a perfect solution in rxjs for this
I would do it all over the socket.
kk thx a lot, then I guess I should go for a socket.on with callback
Idk the name exactly but should be that
So, to create kind of an event emitter with rxjs, I should just create an object with subjects ?
Yeah, I suggest a BehaviourSubject if you want it to keep the most recent state
Otherwise a regular Subject is good too.
If something produces values only it's a Observable, to which you can subscribe a Subject