Home Reference Source

src/utils/network.js

// @ts-check
import { MESSAGE_ADD, MESSAGE_SEND } from '../actionTypes';

import * as connectionActions from '../actions/connection';
import * as messageActions from '../actions/messages';

/**
 * Network manager that handles message sending and receiving.
 * @type {Object}
 * @property {function()} networkManager.init Initilises network client and binds events
 * @property {function()} networkManager.messageReceiveHandler Dispatches redux action when message is received from client
 * @property {function()} networkManager.connectionCloseHandler Dispatches redux action when connection is dropped. Also retries connection.
 * @property {function()} networkManager.connectionRetry Recursively retries network connection
 */
const networkManager = {
    init({ store, client, url }) {
        this.url = url;
        this.dispatch = store.dispatch;
        this.client = client;
        this.store = store;
        this.dispatch(connectionActions.attempted());
        this.subscribed = false;
        this.messageSendHandler = this.messageSendHandler.bind(this);
        this.messageReceiveHandler = this.messageReceiveHandler.bind(this);
        this.connectionCloseHandler = this.connectionCloseHandler.bind(this);
        client
            .init(url)
            .then(_ => {
                this.bindActionEvents();
                this.dispatch(connectionActions.established());
            })
            .catch(error => {
                console.error('react-web-chat connection error: ', error);
                this.connectionRetry();
            });
        this.subscribe();
    },

    messageReceiveHandler(message) {
        this.dispatch(messageActions.messageReceive(message));
    },

    connectionCloseHandler(event) {
        this.dispatch(connectionActions.dropped());
        this.connectionRetry();
    },

    connectionRetry() {
        setTimeout(
            () =>
                this.client
                    .init(this.url)
                    .then(_ => {
                        this.bindActionEvents();
                        this.dispatch(connectionActions.established());
                        this.subscribe();
                    })
                    .catch(error => {
                        console.error('react-web-chat connection error: ', error);
                        this.connectionRetry();
                    }),
            500
        );
    },

    messageSendHandler({ detail: { payload } }) {
        this.client.send(JSON.stringify(payload));
    },

    bindActionEvents() {
        window.addEventListener(`rwc-${MESSAGE_SEND}`, this.messageSendHandler);
    },

    subscribe() {
        this.store.subscribe(() => {
            if (
                !this.subscribed &&
                this.store.getState().connection.established &&
                !this.store.getState().connection.listening
            ) {
                this.client.onmessage(this.messageReceiveHandler);
                this.client.onclose(this.connectionCloseHandler);
                this.store.dispatch(connectionActions.listening());
                this.subscribed = true;
            }
        });
    }
};

export default networkManager;