Чем больше я читаю на эту тему, тем больше похоже на то, что я спускаюсь в кроличью нору. Это новое торговое приложение, которое получает данные в реальном времени через веб-сокеты, основанное на парадигме запроса-ответа. Существует три отдельных 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);
}
}
}
Любой дизайнерский ввод действительно поможет !!





Я написал эту запись в 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);
Упрощенный запрос многомерных выражений был бы похож на запрос sql, но немного сложнее, используемый для аналитики больших данных. ВЫБРАТЬ НЕ ПУСТОЙ {[Меры]. [Stock_Value], [Меры]. [Stock_Prices], [Measure s]. [Stock_Hike_Rate] } ON COLUMNS, NON EMPTY Hierarchize (DrilldownLevel ([Stock]. [StockId]. [StockId]. [ ВСЕ]. [AllMembe r])) В СТРОКАХ ОТ [StockTable] ЗНАЧЕНИЕ СВОЙСТВ ЯЧЕЙКИ '
Да, идея состоит в том, чтобы динамически создавать подписки на веб-сокет, чтобы получать свежие данные о запасах. 1. когда компонент загружается на экран или 2. Пользователь выполняет некоторые действия на странице, выбирая некоторые новые параметры из раскрывающегося списка. Большинство экранов имеют сложные графики, созданные с использованием диаграмм или таблиц React-vis. // onResponse () - это образец обещания. Необходимо предоставить обещание для обработки ответов о подписке. let subscription = bus.channel ('/ StockMarket', {режим: bus.wsModes.PULL}). createListener (this.onResponse.bind (this));
Ха, фанат? Приятно :) Рад, что мои посты были полезны. Помогает ли пример ответить на ваш вопрос (или, по крайней мере, дать вам представление о том, как это может работать в вашем собственном приложении), или есть аспекты, в которых вы все еще не уверены?
Я опробовал ваше решение для своей собственной проблемы, которая включает создание экземпляра сокета только тогда, когда пользователь вошел в систему, и вот как выглядит мой код:
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.info("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.info("Connection closed");
store.dispatch({
type: types.POLL_ACTIVE_SESSIONS_STOP
});
// store.dispatch({ type: TOGGLE_SOCK_OPEN, payload: false });
};
socket.onmessage = e => {
console.info(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;
}
};
};Это не работает, но не могли бы вы указать мне правильное направление? Спасибо.
Привет, Марк, Во-первых, это немного для меня фанатский момент, я, должно быть, прочитал так много ваших сообщений в блоге за последние два года, которые очень помогли мне в разработанных мною приложениях React-Redux.