对于任何试图做我自己的人,我的最终代码如下。我最终意识到我真的需要一个用于连接、发送消息的史诗,以及另一个用于发送消息的史诗。
const notificationTypes = {
WEBSOCKET_TRY_CONNECT: "WEBSOCKET_TRY_CONNECT",
WEBSOCKET_TRY_DISCONNECT: "WEBSOCKET_TRY_DISCONNECT",
WEBSOCKET_CONNECTED: "WEBSOCKET_CONNECTED",
WEBSOCKET_DISCONNECTED: "WEBSOCKET_DISCONNECTED",
WEBSOCKET_ERROR: "WEBSOCKET_ERROR",
WEBSOCKET_MESSAGE_SEND: "WEBSOCKET_MESSAGE_SEND",
WEBSOCKET_MESSAGE_SENT: "WEBSOCKET_MESSAGE_SENT",
WEBSOCKET_MESSAGE_RECIEVED: "WEBSOCKET_MESSAGE_RECIEVED"
};
const notificationActions = {
tryConnect: () => ({ type: notificationTypes.WEBSOCKET_TRY_CONNECT }),
tryDisconnect: () => ({ type: notificationTypes.WEBSOCKET_TRY_DISCONNECT }),
sendNotification: message => ({ type: notificationTypes.WEBSOCKET_MESSAGE_SEND, message }),
sentNotification: message => ({ type: notificationTypes.WEBSOCKET_MESSAGE_SENT, message }),
receivedNotification: message => ({ type: notificationTypes.WEBSOCKET_MESSAGE_RECIEVED, message }),
connected: () => ({ type: notificationTypes.WEBSOCKET_CONNECTED }),
disconnected: () => ({ type: notificationTypes.WEBSOCKET_DISCONNECTED }),
error: error => ({ type: notificationTypes.WEBSOCKET_ERROR, error })
};
let webSocket$ = null;
const notificationSendEpic = (action$, state$) =>
action$.pipe(
ofType(notificationTypes.WEBSOCKET_MESSAGE_SEND),
mergeMap(action => {
if (!webSocket$) {
return of(notificationActions.error(`Attempted to send message while no connection was open.`));
}
webSocket$.next(action.message);
return of(notificationActions.sentNotification(action.message));
})
);
const notificationConnectionEpic = (action$, state$) =>
action$.pipe(
ofType(notificationTypes.WEBSOCKET_TRY_CONNECT),
switchMap(action => {
if (webSocket$) {
return of(notificationActions.error(`Attempted to open connection when one was already open.`));
}
const webSocketOpen$ = new Subject();
const webSocketClose$ = new Subject();
const open$ = webSocketOpen$.pipe(take(1),map(() => of(notificationActions.connected())));
const close$ = webSocketClose$.pipe(take(1),map(() => {
webSocket$ = null;
return of(notificationActions.disconnected());
}));
webSocket$ = webSocket({
url: wsLocation,
openObserver: webSocketOpen$,
closeObserver: webSocketClose$
});
const message$ = webSocket$.pipe(
takeUntil(action$.ofType(notificationTypes.WEBSOCKET_DISCONNECTED, notificationTypes.WEBSOCKET_TRY_DISCONNECT)),
map(evt => of(notificationActions.receivedNotification(evt)))
);
return merge(message$, open$, close$);
}),
mergeMap(v => v)
);