react-logo/frontend/src/sagas/chat.js

98 lines
2.4 KiB
JavaScript

import { call, put, take } from 'redux-saga/effects';
import { eventChannel } from 'redux-saga'
import {
SEND_MESSAGE_FAILURE, SEND_MESSAGE_SUCCESS,
FETCH_MESSAGES_FAILURE, FETCH_MESSAGES_SUCCESS
} from '../actions/chat';
export function* sendMessageSaga(action) {
let result;
try {
result = yield call(sendMessage, action.channel, action.text);
} catch(err) {
yield put({ type: SEND_MESSAGE_FAILURE, err });
}
if ('Error' in result) {
yield put({type: SEND_MESSAGE_FAILURE, err: result.Error});
return
}
yield put({type: SEND_MESSAGE_SUCCESS, data: result.Data });
}
function sendMessage(channel, text) {
return fetch(`http://192.168.0.126:3000/channels/${channel}`, {
method: 'POST',
body: JSON.stringify({
Text: text,
}),
mode: 'cors',
credentials: 'include'
})
.then(res => res.json())
}
export function* fetchMessagesSaga(action) {
let result;
try {
result = yield call(fetchMessages, action.channel);
} catch(err) {
yield put({ type: FETCH_MESSAGES_FAILURE, err });
}
if ('Error' in result) {
yield put({type: FETCH_MESSAGES_FAILURE, err: result.Error});
return
}
yield put({type: FETCH_MESSAGES_SUCCESS, channel: action.channel, data: result.Data });
}
function fetchMessages(channel) {
return fetch(`http://192.168.0.126:3000/channels/${channel}`, {
mode: 'cors',
credentials: 'include'
})
.then(res => res.json())
}
function channelEvents(channel) {
return eventChannel(emitter => {
const eventSource = new EventSource(
`http://192.168.0.126:3000/channels/${channel}/stream`,
{ withCredentials: true }
);
const emit = evt => {
emitter({type: evt.type, data: evt.data});
};
eventSource.addEventListener("joined", emit);
eventSource.addEventListener("left", emit);
eventSource.addEventListener("message", emit);
return () => {
eventSource.removeEventListener("joined", emit)
eventSource.removeEventListener("left", emit)
eventSource.removeEventListener("message", emit)
eventSource.close()
}
}
)
}
export function* streamEventsSaga(action) {
const stream = yield call(channelEvents, action.channel)
while (true) {
let event = yield take(stream)
yield put({ type: 'CHANNEL_EVENT', event: event.type, data: JSON.parse(event.data) });
}
}