Skip to content

Instantly share code, notes, and snippets.

@nickydonna
Last active May 17, 2017 12:34
Show Gist options
  • Save nickydonna/53a9667fd932ac67b17bfe45e6285aa1 to your computer and use it in GitHub Desktop.
Save nickydonna/53a9667fd932ac67b17bfe45e6285aa1 to your computer and use it in GitHub Desktop.
A Redux Middleware for Phoenix Channels
// flow
import type { MiddlewareAPI, Dispatch } from 'redux';
import { Socket } from 'phoenix';
const url = 'ws://localhost:4000/socket';
const usefullAction = [
'CHANNEL_PUSH',
'CHANNEL_DISCONNECT',
'EVENT_CONNECT',
'EVENT_DISCONNECT',
]
let globalSocket;
const channels = {};
let listeningTo = []; //arrayof event in the form room:lobby:event, ie: project:lobby:create
const middleware = ({ dispatch, getState }) =>
(next) =>
(action) =>
{
const { type, payload, meta } = action;
const { auth: { jwt } } = getState();
const connect = () => {
if (globalSocket) return globalSocket;
globalSocket = new Socket(url, { params: { guardian_token: jwt }});
globalSocket.connect();
return globalSocket;
};
const join = (topic) => {
if (channels[topic]) return channels[topic];
const socket = connect();
const channel = socket.channel(topic);
channel.join()
.receive('ok', console.log)
.receive('error', console.log);
channels[topic] = channel;
return channel;
}
const pushMessage = ({ topic, event, payload }) => {
const channel = join(topic, jwt);
channel.push(event, payload);
}
const listenToEvent = ({ topic, event }, meta) => {
const key = `${topic}:${event}`;
if (listeningTo.includes(key)) return;
const channel = join(topic);
channel.on(event, payload =>
dispatch({ type: event, payload, meta })
)
listeningTo = [...listeningTo, key];
}
const stopListenToEvent = ({ topic, event }) => {
const key = `${topic}:${event}`;
if (!listeningTo.includes(key)) return;
const channel = join(topic);
channel.off(event);
listeningTo = listeningTo.filter(e => e !== key);
}
const disconnectChannel = ({ topic }) => {
if (!channels[topic]) return;
const channel = channels[topic];
channel.leave()
channels[topic] = undefined;
}
const result = next(action);
const isUsefullAction = usefullAction.includes(type);
if (!isUsefullAction || !jwt) return result;
if (type === 'CHANNEL_PUSH') pushMessage(payload);
if (type === 'EVENT_CONNECT') listenToEvent(payload, meta);
if (type === 'EVENT_DISCONNECT') stopListenToEvent(payload);
if (type === 'CHANNEL_DISCONNECT') disconnectChannel(payload);
return result;
};
export default middleware;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment