Я борюсь с некоторой ошибкой некоторое время, и недавно я придумал идею причины этой проблемы. Я хочу убедиться, что это действительно является причиной проблемы. Давайте начнем с небольшого описания моей проблемы.
Я пишу приложение, которое подключается к внешней веб-розетке. Этот веб-сокет отправляет мне информацию о текущих чатах на другом сайте. Есть два примера сообщений websocket: chat_closed
(информация о том, что чат с указанным идентификатором завершен) и incoming_event
(информация о новом сообщении в теме с указанным идентификатором чата с указанным идентификатором).
В моем компоненте, где Я обрабатываю сообщения веб-сокета, которые я использую useDispatch
, чтобы получить функцию отправки:
const dispatch = useDispatch()
Вот небольшой план моего обработчика сообщений веб-сокета:
websocketConnection.onmessage = evt => {
const data = JSON.parse(evt.data)
const { chat_id, thread_id, event, action } = data;
switch (action) {
case incomingEventWsAction:
dispatch(pushEvent(chat_id, thread_id, event));
break;
case chatClosedWsAction:
dispatch(closeChat(chat_id));
break;
default:
break;
}
}
pushEvent
и closeChat
return actions:
const pushEvent = (chatId, threadId, event) => ({
type: PUSH_EVENT,
chatId,
threadId,
event,
})
const closeChat = chatId => ({
type: CLOSE_CHAT,
chatId,
})
А вот редуктор, обрабатывающий эти действия (я использую функцию loda sh cloneDeep, чтобы избежать изменения состояния):
function rootReducer(state = initialState, action) {
switch (action.type) {
case PUSH_EVENT: {
const chatsCopy = _.cloneDeep(state.chats)
const targetChat = chatsCopy.find(c => c.id === action.chatId)
targetChat.threads
.find(thread => thread.id === action.threadId)
.events.push(action.event)
return {
...state,
chats: chatsCopy,
}
}
case CLOSE_CHAT: {
const chatsCopy = _.cloneDeep(state.chats)
const targetChat = chatsCopy.find(c => c.id === action.chatId)
targetChat.closed = true;
return {
...state,
chats: chatsCopy
}
}
default:
return state
}
}
А теперь вот пример ситуации:
- В состоянии избыточности у меня есть 2 текущих чата: A и B
- Новое сообщение веб-сокета поступает: новое событие в чате A
- Приложение установлено диспетчерское действие PUSH_EVENT, редуктор захватывает это действие и выполняет код внутри случая коммутатора PUSH_EVENT.
- Во время выполнения кода из 3. поступает новое сообщение websocket: чат B был закрыт
- Приложение отправляет действия на CLOSE_CHAT и ...?
А что происходит сейчас?
- Ожидание редуктора для последнего действия (добавление нового события в чат A и возвращение нового обновленного состояния) быть завершенным, а затем заботится о действии CLOSE_CHAT, используя новое обновленное состояние, которое было возвращено из последнего действия.
- Начинает ли редуктор немедленно выполнять код в случае CLOSE_CHAT, используя то же начальное состояние, что и предыдущее действие PUSH_EVENT? Если это так, это может привести к потере данных, потому что, например, если сначала действие CLOSE_CHAT завершится sh, а затем PUSH_CHAT завершится sh, то PUSH_CHAT вернет состояние, которое получено из исходного состояния, в котором не было информации о чате B будучи закрытым.