Redux saga eventChannel-如何使用不相关动作的退订

时间:2018-08-15 21:13:01

标签: reactjs redux redux-saga

确实是一个复杂的问题,我是Redux-Saga的新手,所以我将尽我所能解释。

我正在为连接聊天产品创建传奇。作为该连接过程的一部分,我必须提供处理程序来处理来自聊天产品的传入事件。有人告诉我Redux-Saga eventChannel是解决此问题的最佳方法,但是我在几个问题上感到困惑。

1)我必须从eventChannel返回一个取消订阅的函数,但是麻烦的是,当事件发射器被破坏时,我不想从聊天管理器中取消订阅。我处理从聊天管理器退订的方法是将连接存储在服务中(单例),并在注销时分派单独的操作,这将导致我的reducer断开连接。那么,当用户注销时,如果不调用Event Emitter的unsubscribe方法,我应该放入unsubscribe的内容是什么?

2)generate()函数似乎无法区分正在发出的事件。因此,如果我想从聊天服务中订阅几种不同类型的事件(用户收到消息,用户加入会议室等),我是否需要大量的eventChannels还是可以发出不同类型的事件?

3)大多数使用事件通道的示例都会先创建某种套接字或连接,然后将其传递给事件通道函数,然后再向其中添加事件。问题在于,Chatkit要求您订阅事件作为连接功能的一部分,因此连接功能必须位于事件通道创建功能内。有问题吗?

现在,我想知道为什么我需要使用事件通道。大概每次导入Chatkit的事件时,我都可以导入动作创建者并调度新动作。没有一个动作是异步的,因此大概可以想像,但是其中许多动作还是可以按顺序正确处理的?

抱歉,有很多问题,并且代码块很长,下面可能有很多错误,但这是我的第一个尝试。

function connect({username, chatManager, tokenProvider}) {

    return eventChannel(emit => {

        const userPresenceHandler = (event) => {
            emit(event.payload)
        }

        const newMessageHandler = (event) => {
            emit(event.payload)
        }

        const errorHandler = (errorEvent) => {
            emit(new Error(errorEvent.reason))
        }

        chatManager.connect({
            onUserCameOnline: userPresenceHandler,
            onUserWentOffline: userPresenceHandler,
        })
        .then(user => {

            user.rooms.map(room =>
                user.subscribeToRoom({
                    roomId: room.id,
                    hooks: {
                        onNewMessage: newMessageHandler
                    },
                })
            )

        })
        .catch(error => console.log('Error on connection', error))


        const unsubscribe = () => {
            // I don't actually want to disconnect the chat manager here
        }

        return unsubscribe

    })

}



function* connectFlow (username) {


    try {

        // Create Chat manager and store it in the chat service
        const newChatManager = new Chatkit.ChatManager({
            instanceLocator: chatConfig.instanceLocator,
            userId: username,
            tokenProvider: chatService.tokenProvider
        })

        chatService.chatManager = newChatManager

        // Attempt the connection
        const newCurrentUser = yield call(connect, {
            username, 
            chatManager: chatService.chatManager, 
            tokenProvider: chatService.tokenProvider
        })

        // Store the currentUser in the chat service
        chatService.currentUser = newCurrentUser

        // Update the connecting state
        yield put(doChatConnectSuccess())



    } catch (error) {

        // Dispatch the error action
        yield put(doChatConnectError({
            statusCode: error.statusCode,
            errors: error.errors || [{message: 'Error connecting to Chatkit:'  + error}]
        }))

    }

}


function* chatConnectSaga () {

    while (true) {

        // Wait for CHAT_CONNECT
        const connectRequest = yield take(CHAT_CONNECT)
        const { username } = connectRequest.payload

        // Check username has been passed in to CHAT_CONNECT
        if(username === undefined){
            return
        }

        // Start a parallel task to do the actual connection
        const connectTask = yield fork(connectFlow, username)

        // Wait for the login to fail or the credentials to be unset
        const action = yield take([CHAT_DISCONNECT, CHAT_CONNECT_ERROR])

        // If CHAT_DISCONNECT was called then cancel any existing attempt to connect
        if (action.type === CHAT_DISCONNECT) yield cancel(connectTask)

    }
}

0 个答案:

没有答案