Redux saga не отправляет действие на живые сокеты

Я пытаюсь отправить действие всякий раз, когда в реальном сокете появляется ответ, используя redux-saga. Мне удалось добраться до строки кода, в которой должно быть помещено (отправлено) действие, но только в этом случае живых сокетов не отправляются живые действия.

Вот мой код:

export function* watchEditorAcceptInvitatioRequest(action) {
    yield takeEvery(START_EDITOR_ACCEPT_INVITATION_SOCKET, edditorAcceptInvitationSocket)
}

export function* edditorAcceptInvitationSocket(action) {
    const {token, user_id} = action.payload
    const subscription = SocketIo.subscribe(token, '/broadcasting/authTest')

    yield put(listenEditorAcceptInvitationSocket())
    let result = yield call(SocketIo.listen, subscription, `new-test-channel.${user_id}`,
        '.new-test-test', (response) => edditorAcceptInvitationReceived({
            func: receiveEditorAcceptInvitationSocket,
            response: response
        }))

}

export function* edditorAcceptInvitationReceived(action) {
    while(true) {

        console.log(action.response) // I am seeing this in response but the action put in blow line
        yield put(action.func(action.response))
    }
}

Ниже приведена подписка на сокет и код прослушивания:

import Echo from 'laravel-echo'
import Socketio from 'socket.io-client'

const BASE_URL = 'https://www.my domain.com'
const PORT = 1111

const subscribe = (token, authEndpoint) => new Echo({
    broadcaster: 'socket.io',
    host: `${BASE_URL}:${PORT}`,
    client: Socketio,
    authEndpoint: authEndpoint,
    auth: {
        headers: {
            Authorization: 'Bearer ' + token,
            Accept: 'application/json',
        },
    },
})

const listen = (echo, channel, event, callback) => {
    echo.private(channel).listen(event, e => {
        const generator = callback(e)
        generator.next()
    })
}

export default {
    subscribe,
    listen
}

То, что здесь отсутствует, будет оценено по достоинству.


person Adnan Ali    schedule 12.02.2021    source источник


Ответы (1)


Мне удалось решить эту проблему с помощью eventChannel

Рабочий код для приведенного выше примера:

export function* watchEditorAcceptInvitatioRequest(action) {
    yield takeEvery(START_EDITOR_ACCEPT_INVITATION_SOCKET, edditorAcceptInvitationSocket)
}

export function* edditorAcceptInvitationSocket(action) {
    const {token, user_id} = action.payload
    const subscription = SocketIo.subscribe(token, '/broadcasting/authTest')
    yield put(listenEditorAcceptInvitationSocket())
    let channel = yield call(SocketIo.listen, subscription, `new-test-channel.${user_id}`,
        '.new-test-test', receiveEditorAcceptInvitationSocket)
    while (true) {
        const action = yield take(channel)
        yield put(action)
    }
}

Ниже представлена ​​обновленная подписка на сокеты и код прослушивания:

импортировать хранилище из '../store/configureStore' импортировать Echo из 'laravel-echo' импортировать Socketio из 'socket.io-client' импортировать {eventChannel} из 'redux-saga'

const BASE_URL = 'https://www.my domain.com'
const PORT = 1111

const subscribe = (token, authEndpoint) => new Echo({
    broadcaster: 'socket.io',
    host: `${BASE_URL}:${PORT}`,
    client: Socketio,
    authEndpoint: authEndpoint,
    auth: {
        headers: {
            Authorization: 'Bearer ' + token,
            Accept: 'application/json',
        },
    },
})

const listen = (echo, channel, event, callback) => {
    return eventChannel( emitter => {
        echo.private(channel).listen(event, e => {
            emitter(store.dispatch(callback(e)))
        })
        return () => {
            console.log('returning channel')
        }
    })}

export default {
    subscribe,
    listen
}
person Adnan Ali    schedule 14.02.2021