Access to context outside of marble.js streams #340
-
Hi guys,
I've eagerly bound dependency injection of What I'm not able to do is to retrieve It looks to me like it's working well while Am I missing something? Is it even possible to access context without Thanks in advance. Regards, |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
@jan-kacina Hi! Could you show me how Thanks! |
Beta Was this translation helpful? Give feedback.
-
Hi @JozefFlakus , Brief description:
Unfortunately, I was not able to get the web socket server from context even when I bound For complete information, I am using WebSocket.org echo test as a simple web socket client. Do I use something in wrong way? Is there anything else I can do to retrieve dependencies stored in context outside of marble.js components? Thanks and regards, |
Beta Was this translation helpful? Give feedback.
-
I think you should rebuild the concept of loginStatusPropagator.ts: export type LoginStatusPropagator = ReturnType<typeof LoginStatusPropagator>;
export const LoginStatusPropagatorToken = createContextToken<LoginStatusPropagator>('LoginStatusPropagator');
export const LoginStatusPropagator = createReader(ask => {
let subscription;
const websocketServer = useContext(WebSocketServerToken)(ask);
const statusSubject$ = new BehaviorSubject<boolean>(false);
const status$ = statusSubject$.asObservable();
const login = () => loginStatusSubject$.next(true);
const logout = () => loginStatusSubject$.next(false);
const teardown = () => subscription && subscription.unsubscribe();
// BTW. there is no real need of having it implemented as a stream
// generally there are plenty of possible ways how it can be implemented, eg. the stream can be modelled as a separate dependency
// and other actions can have their own dependency as well - then they have to inject the stream accordingly
subscription = loginStatus$.subscribe(state =>
websocketServer.clients.forEach(client => client.send(`${state}`)));
return {
login,
logout,
teardown,
status$,
};
}); Then you have to register it eagerly AFTER (thats very important in case of eager bindings!) injected websocket server. export const httpServer = createServer({
port: 1337,
hostname: '127.0.0.1',
listener: listener(),
dependencies: [
bindEagerlyTo(WebSocketServerToken)(async () => await (await wsServer)()),
bindEagerlyTo(LoginStatusPropagatorToken)(LoginStatusPropagator),
],
}); I suppose you want to have this dependency resolved after initial bootstrap of the server. If not then you can use lazy binding. Then in the login effect: export const login$ = r.pipe(
r.matchPath('/login'),
r.matchType('GET'), // are you really sure that it should be a GET request? 🤔
r.useEffect((req$, ctx) => {
// it's better to inject it here (think about returned stream as a React render function 😄)
// https://docs.marblejs.com/other/style-guide#injection
const loginStatusPropagator = useContext(LoginStatusPropagatorToken)(ctx.ask);
return req$.pipe(
tap(() => loginStatusPropagator.login()),
mapTo({ status: HttpStatus.ACCEPTED }),
);
})); |
Beta Was this translation helpful? Give feedback.
I think you should rebuild the concept of
PropagateLoginStatus
and think about it as a complete dependency with all relevant and connected actions inside. You should definitely have a deep dive into the concept of Dependency Injection - it is a powerful mechanism but sometimes hard to understand. I hope the following snippets will help you better understanding the way how it should be implemented :)loginStatusPropagator.ts: