How to tie emitted events events into redux-saga?

后端 未结 5 666
情书的邮戳
情书的邮戳 2020-12-28 18:45

I\'m trying to use redux-saga to connect events from PouchDB to my React.js application, but I\'m struggling to figure out how to connect events emitted from PouchDB to my S

5条回答
  •  长情又很酷
    2020-12-28 18:56

    Thanks to @Yassine Elouafi

    I created short MIT licensed general channels implementation as redux-saga extension for TypeScript language based on solution by @Yassine Elouafi.

    // redux-saga/channels.ts
    import { Saga } from 'redux-saga';
    import { call, fork } from 'redux-saga/effects';
    
    export interface IChannel {
        take(): Promise;
        put(message: TMessage): void;
    }
    
    export function* takeEvery(channel: IChannel, saga: Saga) {
        while (true) {
            const message: TMessage = yield call(channel.take);
            yield fork(saga, message);
        }
    }
    
    export function createChannel(): IChannel {
        const messageQueue: TMessage[] = [];
        const resolveQueue: ((message: TMessage) => void)[] = [];
    
        function put(message: TMessage): void {
            if (resolveQueue.length) {
                const nextResolve = resolveQueue.shift();
                nextResolve(message);
            } else {
                messageQueue.push(message);
            }
        }
    
        function take(): Promise {
            if (messageQueue.length) {
                return Promise.resolve(messageQueue.shift());
            } else {
                return new Promise((resolve: (message: TMessage) => void) => resolveQueue.push(resolve));
            }
        }
    
        return {
            take,
            put
        };
    }
    

    And example usage similar to redux-saga *takeEvery construction

    // example-socket-action-binding.ts
    import { put } from 'redux-saga/effects';
    import {
        createChannel,
        takeEvery as takeEveryChannelMessage
    } from './redux-saga/channels';
    
    export function* socketBindActions(
        socket: SocketIOClient.Socket
    ) {
        const socketChannel = createSocketChannel(socket);
        yield* takeEveryChannelMessage(socketChannel, function* (action: IAction) {
            yield put(action);
        });
    }
    
    function createSocketChannel(socket: SocketIOClient.Socket) {
        const socketChannel = createChannel();
        socket.on('action', (action: IAction) => socketChannel.put(action));
        return socketChannel;
    }
    

提交回复
热议问题