У меня проблемы с подпиской на канал socketcluster (http://socketcluster.io/) при использовании Redux-saga генератор в моем приложении чата. Серверная часть socketcluster настроена таким образом, что любые сообщения сохраняются в базе данных, а затем публикуются в личном канале принимающего пользователя, который назван в честь идентификатора пользователя. Например, пользователь А имеет идентификатор «123abc» и подпишется на канал с именем «123abc» для своих сообщений в реальном времени.
Приведенный ниже код действительно получает новые сообщения, которые публикуются на канале, но он выдает при загрузке «TypeError: Преобразование циклической структуры в JSON» и ломает все мои другие генераторы редукционной саги в приложении. Я копался в Chrome Devtools, и моя теория заключается в том, что это как-то связано с очередью, созданной в функции createChannel. Кроме того, я попытался вернуть отложенное обещание в функции subscribeToChannel, но это также вызвало ошибку циклического преобразования, я могу опубликовать этот код по запросу.
Сначала я сослался на этот ответ: https://stackoverflow.com/a/35288877/5068616, и это помогло мне получить приведенный ниже код на месте, но я не могу найти подобных проблем в Интернете. Также следует отметить, что я использую redux-socket-cluster (https://github.com/mattkrick/redux-socket-cluster) для синхронизации сокета и состояния, но я не думаю, что это корень проблемы
sagas.js
export default function* root() {
yield [
fork(startSubscription),
]
}
function* startSubscription(getState) {
while (true) {
const {
userId
} = yield take(actions.SUBSCRIBE_TO_MY_CHANNEL);
yield call(monitorChangeEvents, subscribeToChannel(userId))
}
}
function* monitorChangeEvents(channel) {
while (true) {
const info = yield call(channel.take) // Blocks until the promise resolves
console.log(info)
}
}
function subscribeToChannel(channelName) {
const channel = createChannel();
const socket = socketCluster.connect(socketConfig);
const c = socket.subscribe(channelName);
c.watch(event => {
channel.put(event)
})
return channel;
}
function createChannel() {
const messageQueue = []
const resolveQueue = []
function put(msg) {
// anyone waiting for a message ?
if (resolveQueue.length) {
// deliver the message to the oldest one waiting (First In First Out)
const nextResolve = resolveQueue.shift()
nextResolve(msg)
} else {
// no one is waiting ? queue the event
messageQueue.push(msg)
}
}
// returns a Promise resolved with the next message
function take() {
// do we have queued messages ?
if (messageQueue.length) {
// deliver the oldest queued message
return Promise.resolve(messageQueue.shift())
} else {
// no queued messages ? queue the taker until a message arrives
return new Promise((resolve) => resolveQueue.push(resolve))
}
}
return {
take,
put
}
}
Спасибо за помощь!