Пользовательский веб-сокет в архитектуре Redux - PullRequest
0 голосов
/ 10 сентября 2018

Чем больше я читаю на эту тему, мне кажется, что я спускаюсь в кроличью нору. Это новое торговое приложение, которое получает данные в реальном времени через веб-сокеты, основанное на парадигме запрос-ответ. Существует три отдельных SPA, в которых, помимо начальной загрузки, каждое действие пользователя инициирует вызов хранилища данных с новым MDXQuery. Поэтому, в свою очередь, мне нужно было бы сделать новые подписки на componentDidMount (), а также на соответствующих ActionCreators. Я хотел бы упростить код, чтобы избежать дублирования кода и избыточности.

Приведенный ниже код помогает установить новый канал подписки для потоковой передачи ответа через веб-сокет (в отличие от большинства кодов sockets.io, где он идет с назначенным открытием, закрытием, отправкой)

    this.subscription = bus.channel(PATH, { mode: bus.wsModes.PULL }).createListener(this.onResponse.bind(this));
this.subscription.subscribe(MDXQuery);

Если я прочитал документацию REDUX о том, где я должен разместить код веб-сокета? Упоминается создание пользовательского промежуточного программного обеспечения. ССЫЛКА: https://redux.js.org/faq/codestructure#where-should-websockets-and-other-persistent-connections-live

Но я не очень уверен, как я мог бы использовать этот пользовательский код веб-сокета для создания собственного промежуточного программного обеспечения или на уровне компонентов, чтобы имитировать эту стратегию.

const createMySocketMiddleware = (url) => {
return storeAPI => {
    let socket = createMyWebsocket(url);

    socket.on("message", (message) => {
        storeAPI.dispatch({
            type : "SOCKET_MESSAGE_RECEIVED",
            payload : message
        });
    });

    return next => action => {
        if(action.type == "SEND_WEBSOCKET_MESSAGE") {
            socket.send(action.payload);
            return;
        }

        return next(action);
    }
}

}

Любые входные данные действительно помогут !!

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Я опробовал ваше решение для моей собственной проблемы, которая заключается в создании экземпляра сокета только тогда, когда пользователь вошел в систему, и вот как выглядит мой код:

const socketMiddleWare = url => store => {
  const socket = new SockJS(url, [], {
    sessionId: () => custom_token_id
  });
  return next => action => {
    switch (action.type) {
      case types.USER_LOGGED_IN:
        {
          socket.onopen = e => {
            console.log("Connection", e.type);

            store.dispatch({
              type: types.TOGGLE_SOCK_OPENING
            });

            if (e.type === "open") {
              store.dispatch({
                type: types.TOGGLE_SOCK_OPENED
              });
              createSession(custom_token_id, store);
              const data = {
                type: "GET_ACTIVE_SESSIONS",
                JWT_TOKEN: Cookies.get("agentClientToken")
              };
              store.dispatch({
                type: types.GET_ACTIVE_SESSIONS,
                payload: data
              });
            }
          };
          socket.onclose = () => {
            console.log("Connection closed");
            store.dispatch({
              type: types.POLL_ACTIVE_SESSIONS_STOP
            });
            // store.dispatch({ type: TOGGLE_SOCK_OPEN, payload: false });
          };
          socket.onmessage = e => {
            console.log(e)
          };
          if (
            action.type === types.SEND_SOCKET_MESSAGE
          ) {
            socket.send(JSON.stringify(action.payload));
            return;
          } else if (action.type === types.USER_LOGGED_OUT) {
            socket.close();
          }
          next(action);
        }
      default:
        next(action);
        break;
    }
  };
};

Хотя это не работает, но не могли бы вы указать мне правильное направление. Спасибо.

0 голосов
/ 10 сентября 2018

Я написал эту запись и пример FAQ.

Если я понимаю ваш вопрос, вы спрашиваете, как динамически создавать дополнительные подписки во время выполнения?

Поскольку промежуточное ПО Redux может видеть каждое отправленное действие, которое передается через конвейер промежуточного ПО, выможет отправлять действия, которые предназначены только для выполнения командами промежуточного программного обеспечения.Теперь я не уверен, что такое MDXQuery, и также неясно, что вы хотите делать с сообщениями, полученными из этих подписок.В качестве примера я предполагаю, что вы хотите либо отправлять действия Redux при каждом получении сообщения подписки, либо потенциально выполнять с ними некоторую настраиваемую логику.

Вы можете написать собственное промежуточное ПО, которое прослушивает действиякак "CREATE_SUBSCRIPTION" и "CLOSE_SUBSCRIPTION", и потенциально принимает функцию обратного вызова для запуска при получении сообщения.

Вот как это может выглядеть:

// Add this to the store during setup
const subscriptionMiddleware = (storeAPI) => {
    let nextSubscriptionId = 0;
    const subscriptions = {};
    const bus = createBusSomehow();

    return (next) => (action) => {
        switch(action.type) {
            case "CREATE_SUBSCRIPTION" : {
                const {callback} = action;
                const subscriptionId = nextSubscriptionId;
                nextSubscriptionId++;

                const subscription = bus.channel(PATH, { mode: bus.wsModes.PULL })
                                        .createListener((...args) => {
                                            callback(dispatch, getState, ...args);
                                        });
                subscriptions[subscriptionId] = subscription;
                return subscriptionId;
            }
            case "CLOSE_SUBSCRIPTION" : {
                const {subscriptionId} = action;
                const subscription = subscriptions[subscriptionId];

                if(subscription) {
                    subscription.close();
                    delete subscriptions[subscriptionId];
                }
                return;
            }
        }
    }
}

// Use over in your components file
function createSubscription(callback) {
    return {type : "CREATE_SUBSCRIPTION", callback };
}

function closeSubscription(subscriptionId) {
    return {type :  "CLOSE_SUBSCRIPTION", subscriptionId};
}

// and in your component:
const actionCreators = {createSubscription, closeSubscription};

class MyComponent extends React.Component {
    componentDidMount() {
        this.subscriptionId = this.props.createSubscription(this.onMessageReceived);
    }

    componentWillUnmount() {
        this.props.closeSubscription(this.subscriptionId);
    }
}

export default connect(null, actionCreators)(MyComponent);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...