Redux-saga и подписка на сокеты вызывают Uncaught TypeError: Преобразование циклической структуры в JSON

У меня проблемы с подпиской на канал 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
    }
}

Спасибо за помощь!


person gpsamson    schedule 10.06.2016    source источник
comment
› Преобразование циклической структуры в JSON Может быть, просто выполнить предыдущую ручную сериализацию в JSON, которая учитывает циклическую структуру JSON, и использовать вторые параметры в функции JSON.stringify для разрешения обратных ссылок. Более того, существует множество библиотек, которые это делают.   -  person Vladislav Ihost    schedule 05.07.2017