Redux:如何让两个减速机以特定的顺序响应相同的操作?
我对Redux比较陌生,我有以下情况:Redux:如何让两个减速机以特定的顺序响应相同的操作?,redux,Redux,我对Redux比较陌生,我有以下情况: 我的应用程序发出AJAX请求,从服务器获取第一个“message”对象 响应返回并发送{type:'RECEIVE_FIRST_MESSAGE',MESSAGE} 我的MessageReducer通过以下方式处理RECEIVE\u FIRST\u MESSAGE: A) 将action.message添加到state.messages B) 进行另一个AJAX调用以获取下一条消息(如果action.message.hasNextMessage) MySes
{type:'RECEIVE_FIRST_MESSAGE',MESSAGE}
MessageReducer
通过以下方式处理RECEIVE\u FIRST\u MESSAGE
:
A) 将action.message
添加到state.messages
B) 进行另一个AJAX调用以获取下一条消息(如果action.message.hasNextMessage
)SessionReducer
还通过将action.MESSAGE.sessionId
添加到state.session.id
来处理RECEIVE\u FIRST\u MESSAGE
sessionId
。但是由于MessageReducer
在SessionReducer
之前运行,会话ID在MessageReducer
尝试发出第二个AJAX请求时不处于状态
我可以通过使用超时来“解决”这个问题,以确保MessageReducer
在1毫秒后才发出第二个请求,但这感觉像是一种黑客/反模式
TLDR
当我有:
- 具有
状态两部分数据的动作(由两个不同的减速器处理)
- 我想触发一个AJAX调用作为响应,它来自一个reducer
- 我想添加一些状态(
)作为响应,来自reducer Bstate.session.id
如何确保reducer B在reducer A调用AJAX之前添加状态(以一种不会让Dan Abramov哭的方式)?第一件事。决不要从减速器内部进行AJAX调用。永远 Reducer函数应该是纯粹的,没有任何副作用(比如HTTP请求)。相反,使用thunks对你有利。下面是一个示例,说明了您可能如何做到这一点 从服务器返回第一条消息响应后,您将调度
RECEIVE\u first\u message
操作。这将同步更新原子状态。完成后,您可以检查消息是否有下一条消息。如果是,则调度一个新的异步操作以获取下一条消息。在该异步操作创建者中,您可以从状态原子获取会话ID,该会话ID保证会更新以响应您先前调度的RECEIVE\u FIRST\u消息
操作
如果你有任何问题,请告诉我
// getFirstMessageFromServer() and getNextMessageFromServer() are thunks and async action creators
// fetchFirstMessage() and fetchNextMessage() make HTTP requests
function getFirstMessageFromServer() {
return (dispatch, getState) => {
return fetchFirstMessage()
.then(message => {
dispatch({ type: 'RECEIVE_FIRST_MESSAGE', message });
if (message.hasNextMessage) dispatch(getNextMessageFromServer());
return message;
});
};
}
function getNextMessageFromServer() {
return (dispatch, getState) => {
const { id: sessionId } = getState().session.id;
return fetchNextMessage(sessionId)
.then(nextMessage => {
dispatch({ type: 'RECEIVE_NEXT_MESSAGE', message: nextMessage });
return nextMessage;
});
};
}
const rootReducer = combineReducers({
session: sessionReducer,
messages: messagesReducer
});
const initialMessages = [];
function messagesReducer(state = initialMessages, action) {
switch(action.type) {
case 'RECEIVE_FIRST_MESSAGE':
return state.concat(action.message);
case 'RECEIVE_NEXT_MESSAGE':
return state.concat(action.message);
default:
return state;
}
}
const initialSession = { id: null };
function sessionReducer(state = initialSession, action) {
switch(action.type) {
case 'RECEIVE_FIRST_MESSAGE':
return {
...state,
id: action.message.sessionId
};
default:
return state;
}
}
第一件事。决不要从减速器内部进行AJAX调用。永远 Reducer函数应该是纯粹的,没有任何副作用(比如HTTP请求)。相反,使用thunks对你有利。下面是一个示例,说明了您可能如何做到这一点 从服务器返回第一条消息响应后,您将调度
RECEIVE\u first\u message
操作。这将同步更新原子状态。完成后,您可以检查消息是否有下一条消息。如果是,则调度一个新的异步操作以获取下一条消息。在该异步操作创建者中,您可以从状态原子获取会话ID,该会话ID保证会更新以响应您先前调度的RECEIVE\u FIRST\u消息
操作
如果你有任何问题,请告诉我
// getFirstMessageFromServer() and getNextMessageFromServer() are thunks and async action creators
// fetchFirstMessage() and fetchNextMessage() make HTTP requests
function getFirstMessageFromServer() {
return (dispatch, getState) => {
return fetchFirstMessage()
.then(message => {
dispatch({ type: 'RECEIVE_FIRST_MESSAGE', message });
if (message.hasNextMessage) dispatch(getNextMessageFromServer());
return message;
});
};
}
function getNextMessageFromServer() {
return (dispatch, getState) => {
const { id: sessionId } = getState().session.id;
return fetchNextMessage(sessionId)
.then(nextMessage => {
dispatch({ type: 'RECEIVE_NEXT_MESSAGE', message: nextMessage });
return nextMessage;
});
};
}
const rootReducer = combineReducers({
session: sessionReducer,
messages: messagesReducer
});
const initialMessages = [];
function messagesReducer(state = initialMessages, action) {
switch(action.type) {
case 'RECEIVE_FIRST_MESSAGE':
return state.concat(action.message);
case 'RECEIVE_NEXT_MESSAGE':
return state.concat(action.message);
default:
return state;
}
}
const initialSession = { id: null };
function sessionReducer(state = initialSession, action) {
switch(action.type) {
case 'RECEIVE_FIRST_MESSAGE':
return {
...state,
id: action.message.sessionId
};
default:
return state;
}
}
你用的是像redux thunks或sagas这样的东西吗?如果它已经在您正在处理的消息中,为什么需要从会话中获取它?但是:你在减速器中调用Ajax?是的,我在使用thunks。至于为什么我会从
状态获取ID
。。。我想现在我想起来了,我不知道。我只是在想“一个操作会将ID添加到状态,一个单独的操作会将ID从状态中拉出来”,但是由于(正如您所指出的)我已经在操作中拥有了我所需要的一切,所以通过状态
传递ID是完全没有必要的(好吧,除了以后的请求,但是这些请求没有时间问题)。谢谢如果你想让某样东西达到“根据定义,在这种情况下,你已经拥有了你所需要的一切”的效果,我很乐意接受。你使用的是redux thunks或sagas之类的东西吗?如果它已经在您正在处理的消息中,为什么需要从会话中获取它?但是:你在减速器中调用Ajax?是的,我在使用thunks。至于为什么我会从状态获取ID
。。。我想现在我想起来了,我不知道。我只是在想“一个操作会将ID添加到状态,一个单独的操作会将ID从状态中拉出来”,但是由于(正如您所指出的)我已经在操作中拥有了我所需要的一切,所以通过状态
传递ID是完全没有必要的(好吧,除了以后的请求,但是这些请求没有时间问题)。谢谢如果你想让某些东西达到“根据定义,在这种情况下,你已经拥有了你所需要的一切”的效果,我会很乐意接受它。这是有道理的:当我有一分钟的时间时,我会尝试从减速器中重构委托调用,并遵循你的模式。谢谢。这很有意义:当我有时间的时候,我会尝试从reducer中重构委托调用,并遵循您的模式。谢谢